Imports System.ComponentModel
Imports IntraSell_DLL

Public Class EANAutoComplete

    Dim scAutoComplete As New AutoCompleteStringCollection
    Dim EANColIndex As Integer
    Dim ArtNrColIndex As Integer 'where to write the ArtNr 
    Dim BezeichnungColIndex As Integer 'where to write Bezeichnung
    Dim SpezifikationColIndex As Integer 'für Sortierung nach EAN, Hidden column
    Dim aktiveArtikel As New Dictionary(Of String, Object)  'EAN is the Key (UPPER CASE)
    Dim aktiveArtikelNachArtNr As New Dictionary(Of Integer, Object)  'ArtNr is the Key 
    Dim dg As DataGridView

    Property IgnoreEventsDuringBinding As Boolean = False

    Const EAN_UNKNOWN As String = "???"

    Public Sub New(dg As DataGridView, EANColIndex As Integer, ArtNrColIndex As Integer, BezeichnungColIndex As Integer, SpezifikationColIndex As Integer)
        Me.dg = dg
        Me.EANColIndex = EANColIndex
        Me.ArtNrColIndex = ArtNrColIndex
        Me.BezeichnungColIndex = BezeichnungColIndex
        Me.SpezifikationColIndex = SpezifikationColIndex
        AddHandler ModuleArtikel.ArtikelStammdatenGeaendert, AddressOf BuildAutocomplete
    End Sub

    Sub MakeEANColumnAutocomplete()
        AddHandler dg.KeyDown, AddressOf DataGridView1_KeyDown
        AddHandler dg.CellFormatting, AddressOf DataGridView1_CellFormatting
        AddHandler dg.CellValidating, AddressOf DataGridView1_CellValidating
        AddHandler dg.EditingControlShowing, AddressOf DataGridView1_EditingControlShowing
        AddHandler dg.CellMouseDoubleClick, AddressOf DataGridView1_CellMouseDoubleClick
        AddHandler dg.ColumnHeaderMouseClick, AddressOf DataGridView1_ColumnHeaderMouseClick
        BuildAutocomplete()
    End Sub

    Private Sub DataGridView1_CellFormatting(sender As Object, e As DataGridViewCellFormattingEventArgs) 'Handles DataGridView1.CellFormatting

        If IgnoreEventsDuringBinding Then
            Exit Sub
        End If
        If e.ColumnIndex = EANColIndex Then
            Try

                Dim ArtNr = dg(ArtNrColIndex, e.RowIndex).Value
                Dim eanCell As DataGridViewCell = dg(EANColIndex, e.RowIndex)
                Dim OldEANValue = eanCell.Value

                'Debug.Print("DataGridView1_CellFormatting " + OldEANValue)

                If eanCell.ToolTipText = "" Then
                    eanCell.ToolTipText = "CTRL Taste - Artikelsuche"
                End If

                If OldEANValue IsNot Nothing Then
                    Exit Sub
                End If

                If Not IsNumeric(ArtNr) Then
                    eanCell.Value = EAN_UNKNOWN
                    Exit Sub
                End If

                If ArtNr = 0 Then
                    eanCell.Value = EAN_UNKNOWN
                    Exit Sub
                End If

                Dim artikelRow = aktiveArtikelNachArtNr(ArtNr)
                If OldEANValue <> artikelRow("EAN") Then
                    eanCell.Value = artikelRow("EAN")
                    eanCell.Style.ForeColor = Color.Blue
                End If
            Catch ex As Exception
                'nicht vorhanden
                'Debug.Print("Fehler in DataGridView1_CellFormatting " & ex.Message)
                dg(EANColIndex, e.RowIndex).Value = EAN_UNKNOWN
            End Try
        End If

    End Sub

    Private Sub DataGridView1_CellValidating(sender As Object, e As System.Windows.Forms.DataGridViewCellValidatingEventArgs)
        'Debug.Print("DataGridView1_CellValidating")
        If IgnoreEventsDuringBinding Then
            Exit Sub
        End If

        If e.ColumnIndex = EANColIndex Then
            'Debug.Print("DataGridView1_CellValidating FormattedValue" & e.FormattedValue.ToString)

            Dim FormattedValueToSpace = e.FormattedValue.ToString

            Dim val = dg(e.ColumnIndex, e.RowIndex).Value
            Dim tag = dg(e.ColumnIndex, e.RowIndex).Tag
            Try
                If val IsNot Nothing And val = tag Then 'NUR FÜR TEST, Weil ich nicht finden kann wie formatted value von den tests zu setzen ist
                    FormattedValueToSpace = tag
                End If
            Catch ex As Exception

            End Try

            If FormattedValueToSpace.Contains(" ") Then
                FormattedValueToSpace = FormattedValueToSpace.Split(" ")(0)
            End If
            FormattedValueToSpace = UppercaseFirstLetter(FormattedValueToSpace)
            'Fin from AutoComplete
            'Dim possibleEAN = UppercaseFirstLetter(e.FormattedValue.ToString)
            'Find in Index 
            Dim artikelRow = Nothing
            Try
                If FormattedValueToSpace <> "???" Then
                    If aktiveArtikel.ContainsKey(FormattedValueToSpace) Then
                        artikelRow = aktiveArtikel(FormattedValueToSpace)
                    End If
                End If

            Catch ex As Exception
                'key not found
            End Try

            If artikelRow Is Nothing Then
                'If Not scAutoComplete.Contains(possibleEAN) Then
                'MessageBox.Show("Invalid Entry")
                'e.Cancel = True
            Else
                EANNrGueltig(FormattedValueToSpace, e.RowIndex)
            End If
        End If

        If e.ColumnIndex = BezeichnungColIndex Then
            Try
                Dim ArtNr = dg(ArtNrColIndex, e.RowIndex).Value
                If Not IsDBNull(ArtNr) Then
                    If ArtNr IsNot Nothing Then
                        Dim oldBezeichnung = dg(e.ColumnIndex, e.RowIndex).Value
                        Dim artikelRow = aktiveArtikelNachArtNr(ArtNr)
                        Dim bezeichnung = artikelRow("Bezeichnung")
                        If IsUndefined(oldBezeichnung) Then
                            dg(e.ColumnIndex, e.RowIndex).Value = bezeichnung
                        End If
                    End If
                End If
            Catch ex As Exception
                Debug.Print("Fehler in DataGridView1_CellValidating " & ex.Message)
            End Try
        End If
    End Sub

    Private Function UppercaseFirstLetter(val As String) As String
        ' Test for nothing or empty.
        If String.IsNullOrEmpty(val) Then
            Return val
        End If

        ' Convert to character array.
        Dim array() As Char = val.ToCharArray

        ' Uppercase first character.
        array(0) = Char.ToUpper(array(0))

        ' Return new string.
        Return New String(array)
    End Function

    Private Function ToProperCase(s As String) As String
        Return StrConv(s, VbStrConv.ProperCase)
    End Function

    'ArtNr und Bezeichnung setzen 
    Private Sub EANNrGueltig(EAN As String, RowIndex As Integer)
        'Debug.Print("EANNrGueltig " & EAN & " " & RowIndex)
        Dim artikelRow = aktiveArtikel(EAN)

        Dim curVal = dg(ArtNrColIndex, RowIndex).Value
        If Not IsDBNull(curVal) Then
            If curVal = artikelRow("ArtNr") Then
                Exit Sub
            End If
        End If
        dg(ArtNrColIndex, RowIndex).Value = artikelRow("ArtNr")
        dg(BezeichnungColIndex, RowIndex).Value = artikelRow("Bezeichnung")

    End Sub

    Private Sub DataGridView1_EditingControlShowing(sender As Object, e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) 'Handles DataGridView1.EditingControlShowing
        'Debug.Print("DataGridView1_EditingControlShowing")

        If dg.CurrentCell.ColumnIndex = EANColIndex AndAlso TypeOf e.Control Is TextBox Then
            With DirectCast(e.Control, TextBox)
                .AutoCompleteMode = AutoCompleteMode.SuggestAppend
                .AutoCompleteSource = AutoCompleteSource.CustomSource
                .AutoCompleteCustomSource = scAutoComplete
            End With
        Else
            If TypeOf e.Control Is TextBox Then
                '21.04.2021 - not sure what this logic means, but causes exceptions
                With DirectCast(e.Control, TextBox)
                    .AutoCompleteMode = AutoCompleteMode.None 'Reset AC / may have problems with others that set Auto complete to something 
                End With
            End If

        End If
    End Sub

    Private Sub BuildAutocomplete()
        aktiveArtikel = New Dictionary(Of String, Object)  'EAN is the Key (UPPER CASE)
        aktiveArtikelNachArtNr = New Dictionary(Of Integer, Object)  'ArtNr is the Key 

        'Debug.Print("BuildAutocomplete")
        Dim cmd = New MySql.Data.MySqlClient.MySqlCommand("select EAN, ArtNr, Bezeichnung, ProduktAktiv from grArtikel where EAN is not null order by EAN") With {
            .Connection = CurrentDB
        }
        Dim artikel = TryGetFromCache(cmd)
        For Each r In artikel.Rows
            Try
                If (r("ProduktAktiv")) Then
                    'scAutoComplete.Add(r("EAN"))
                    scAutoComplete.Add(r("EAN") & " " & r("Bezeichnung"))
                End If
                Dim ean = r("EAN")
                If Not IsDBNull(ean) Then
                    If Not aktiveArtikel.ContainsKey(ean) Then
                        aktiveArtikel.Add(r("EAN"), r)
                    End If
                End If

                aktiveArtikelNachArtNr.Add(r("ArtNr"), r)
            Catch ex As Exception
                Debug.Print("Warning: BuildAutocomplete " & ex.Message)
            End Try
        Next
    End Sub

#Region "Artikel wahl"


    Dim SelectedRowIndex As Integer

    ''' <summary>
    ''' Reagiert auf Control , Context Menu or BrowserSearch 
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub DataGridView1_KeyDown(sender As Object, e As KeyEventArgs)
        'Debug.Print("DataGridView1_KeyDown " & e.KeyCode)

        If dg.SelectedCells.Count = 1 Then
            Dim ColumnIndex = dg.SelectedCells(0).ColumnIndex
            Dim RowIndex = dg.SelectedCells(0).RowIndex

            If ColumnIndex = EANColIndex Then
                Dim currentEAN = dg(ColumnIndex, RowIndex).Value
                ' If Not IsDBNull(currentEAN) Then
                '     Debug.Print(currentEAN)
                ' End If
                ' Debug.Print("e.KeyCode=" & e.KeyCode)
                'Reagiert auf Control , Context Menu or BrowserSearch
                If (e.KeyCode = Keys.ControlKey Or e.KeyCode = 93 Or e.KeyCode = Keys.BrowserSearch) Then
                    ArtikelSelectorButton_Click(RowIndex, currentEAN)
                    Exit Sub
                End If
            End If
        End If
    End Sub

    Private Sub ArtikelSelectorButton_Click(SelectedRowIndex As Integer, EAN As String) ' Handles SelectorButton.Click
        Try
            'Debug.Print("ArtikelSelectorButton_Click " & SelectedRowIndex)
            Me.SelectedRowIndex = SelectedRowIndex
            Dim artikelSelector = New ArtikelSelector
            artikelSelector.SucheNach(EAN)
            AddHandler artikelSelector.ArtikelAuswahl, AddressOf ArtikelAuswahl
            artikelSelector.ShowDialog()
        Catch ex As Exception
            HandleAppError(ex)
        End Try
    End Sub

    Private Sub ArtikelAuswahl(ArtNr As Integer, EAN As String)
        Try
            'Debug.Print("ArtikelAuswahl " & ArtNr & " " & EAN)
            dg(EANColIndex, SelectedRowIndex).Value = EAN
            EANNrGueltig(EAN, SelectedRowIndex)
        Catch ex As Exception
            HandleAppError(ex)
        End Try
    End Sub

    Private Sub DataGridView1_CellMouseDoubleClick(sender As Object, e As DataGridViewCellMouseEventArgs)
        Try
            'Debug.Print("DataGridView1_CellMouseDoubleClick " & SelectedRowIndex)
            Dim ColumnIndex = e.ColumnIndex
            Dim RowIndex = e.RowIndex
            If ColumnIndex = EANColIndex Then
                Dim ean = dg(ColumnIndex, e.RowIndex).Value
                ArtikelSelectorButton_Click(RowIndex, ean)
                'If IsUndefined(ean) Then
                '    'Öffne Artikel Auswahl 
                '    ArtikelSelectorButton_Click(RowIndex)
                'Else
                '    OffneArtikelMaskeByFilter("EAN='" & ean & "'")
                'End If
            End If
        Catch ex As Exception
            HandleAppError(ex)
        End Try
    End Sub

    Private Function IsUndefined(val As Object) As Boolean
        If IsDBNull(val) Then
            Return True
        End If
        If val = EAN_UNKNOWN Or val Is Nothing Then
            Return True
        End If
        Return False
    End Function

#End Region

    ''' <summary>
    ''' Sort EAN Spalte nach Spezifikation Spalte (Workaround für nicht gebundene Spalte)
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub DataGridView1_ColumnHeaderMouseClick(sender As Object, e As DataGridViewCellMouseEventArgs)

        If (e.ColumnIndex = EANColIndex) Then
            SortEAN()
        Else
            Dim colEAN As DataGridViewColumn = dg.Columns(EANColIndex)
            If colEAN.HeaderCell.SortGlyphDirection = SortOrder.Ascending Then
                colEAN.HeaderCell.SortGlyphDirection = SortOrder.None
            End If
        End If

    End Sub

    ''' <summary>
    ''' 
    ''' </summary>
    ''' <remarks></remarks>
    Sub SortEAN()
        Dim oldIgnoreEvenets = IgnoreEventsDuringBinding
        Try
            IgnoreEventsDuringBinding = True

            For Each r As DataGridViewRow In dg.Rows
                Try
                    Dim ArtNr = r.Cells(ArtNrColIndex).Value
                    Dim artikelRow = aktiveArtikelNachArtNr(ArtNr)
                    r.Cells(SpezifikationColIndex).Value = artikelRow("EAN")
                Catch ex As Exception

                End Try
            Next

            Dim col As DataGridViewColumn = dg.Columns(EANColIndex)
            Dim col_sort As DataGridViewColumn = dg.Columns(SpezifikationColIndex)

            dg.Sort(col_sort, ListSortDirection.Ascending)

            col.HeaderCell.SortGlyphDirection = SortOrder.Ascending

        Catch ex As Exception
        Finally
            IgnoreEventsDuringBinding = oldIgnoreEvenets
        End Try
    End Sub

    ''' <summary>
    ''' 
    ''' </summary>
    ''' <remarks></remarks>
    Sub RepeatSortEAN()
        'Repeat Sort EAN 
        Dim col As DataGridViewColumn = dg.Columns(EANColIndex)
        If col.HeaderCell.SortGlyphDirection = SortOrder.Ascending Then
            SortEAN()
        End If
    End Sub


End Class