Namespace ControlLoader

    Public Class _BaseControl

        Public Shared Function ReplaceSqlCommandPlaceholders(sqlCommand As String, recordId As Integer, parentRecordId As Integer)
            sqlCommand = sqlCommand.Replace("@RECORD_ID", recordId)
            sqlCommand = sqlCommand.Replace("@RECORDID", recordId)
            sqlCommand = sqlCommand.Replace("@PARENTRECORD_ID", parentRecordId)
            sqlCommand = sqlCommand.Replace("@PARENTRECORDID", parentRecordId)

            Return sqlCommand
        End Function

        Public Shared Function LoadAutoValue(control As Windows.Forms.Control, RecordId As Integer, ParentRecordId As Integer)
            Try
                Dim AutoValue As String = String.Empty
                Dim ControlId As Integer = DirectCast(control.Tag, ClassControlMetadata).Id
                Dim CONNID = ClassDatabase.Execute_Scalar(String.Format("SELECT CONNECTION_ID_1 FROM TBPMO_CONTROL WHERE GUID = {0}", ControlId))
                Dim SQL As String = ClassDatabase.Execute_Scalar(String.Format("SELECT SQL_COMMAND_1 FROM TBPMO_CONTROL WHERE GUID = {0}", ControlId))
                SQL = ClassControlValues.ReplaceSqlCommandPlaceholders(SQL, RecordId, ParentRecordId)

                If SQL = "" Or IsDBNull(SQL) Then
                    Return Nothing
                End If

                If Not IsNothing(CONNID) Then
                    AutoValue = ClassDatabase.Execute_ScalarWithConnection(CONNID, SQL)
                Else
                    AutoValue = ClassDatabase.Execute_Scalar(SQL)
                End If
                ' AutoValue = ClassDatabase.Execute_Scalar(SQL)

                If String.IsNullOrEmpty(AutoValue) Or IsDBNull(AutoValue) Then
                    Return Nothing
                End If

                Return AutoValue
            Catch ex As Exception
                ClassLogger.Add("Unexpected Error in LoadAutoValue: " & ex.Message, True)
                Return Nothing
            End Try
           

        End Function

    End Class

    Public Class _ListControl : Inherits _BaseControl

        Public Shared Function GetDynamicValue(controlId As Integer, formId As Integer, connID As Object, sqlCommand As String) As DynamicValue
            Dim returnValue As DynamicValue

            returnValue.StaticList = CheckForStaticList(controlId)
            returnValue.DataTable = GetSqlList(controlId, formId, connID, sqlCommand)

            Return returnValue
        End Function

        Private Shared Function CheckForStaticList(controlId As Integer) As List(Of String)
            Try
                ' Der alte SQL Befehl hat nicht wirklich nach der StaticList geschaut o_O
                ' Dim SQL As String = String.Format("SELECT VALUE FROM VWPMO_VALUES WHERE CONTROL_ID = {0} AND RECORD_ID = {1}", controlId, recordId)
                Dim SQL As String = String.Format("SELECT STATIC_LIST FROM TBPMO_CONTROL WHERE GUID = {0}", controlId)
                Dim staticList As String = ClassDatabase.Execute_Scalar(SQL)

                If IsNothing(staticList) Or String.IsNullOrWhiteSpace(staticList) Then
                    Return Nothing
                Else
                    Return New List(Of String)(staticList.Split(";").ToArray())
                End If
            Catch ex As Exception
                MsgBox("Error in CheckForStaticList: " & vbNewLine & ex.Message)
                Return Nothing
            End Try
        End Function

        Public Shared Function GetSqlList(controlId As Integer, formId As Integer, connection_Id As Object, sqlCommand As String) As DataTable
            Try
                If sqlCommand Is Nothing Or sqlCommand = String.Empty Then
                    Return Nothing
                End If

                Dim cached As DataTable = ClassControlValueCache.LoadFromCache(sqlCommand)
                Dim final As DataTable

                If cached Is Nothing Then
                    If Not IsDBNull(connection_Id) Then
                        final = ClassDatabase.MSSQL_ReturnDTWithConnection(connection_Id, sqlCommand)
                    Else
                        final = ClassDatabase.Return_Datatable(sqlCommand)
                    End If

                    ClassControlValueCache.SaveToCache(sqlCommand, final)
                    Console.WriteLine("CACHE MISS")
                Else
                    final = cached
                    Console.WriteLine("CACHE HIT")
                End If

                Return final
            Catch ex As Exception
                MsgBox("Error in GetSqlList: " & vbNewLine & ex.Message)
                Return Nothing
            End Try
        End Function

        Overloads Shared Sub SetDataSource(control As Windows.Forms.ComboBox, dt As DataTable)
            Dim sw As Stopwatch = Stopwatch.StartNew()
            Dim columnCount As Integer = dt.Columns.Count

            control.BeginUpdate()

            ' Damit beim Setzen von DisplayMember und ValueMember kein Fehler auftritt, 
            ' muss die Datasource zunächst geleert werden und der selected index auf -1 gesetzt werden.
            control.DataSource = Nothing
            control.SelectedIndex = -1

            ' Es ist wichtig, dass DisplayMember und ValueMember VOR der DataSource festgelegt werden,
            ' Dadurch ist das Laden der Datasource um einiges SCHNELLER
            If columnCount = 1 Then
                control.DisplayMember = dt.Columns(0).ColumnName
                control.ValueMember = dt.Columns(0).ColumnName
            ElseIf columnCount = 2 Then
                control.DisplayMember = dt.Columns(1).ColumnName
                control.ValueMember = dt.Columns(0).ColumnName
            End If

            ' Als letztes setzen wir die DataSource
            control.DataSource = dt

            control.EndUpdate()

            sw.Stop()
            Console.WriteLine("SetDataSource for {0} took {1}ms", control.Name, sw.ElapsedMilliseconds)
        End Sub

        Overloads Shared Sub SetDataSource(control As DevExpress.XtraEditors.CheckedListBoxControl, dt As DataTable)
            Dim columnCount As Integer = dt.Columns.Count

            ' Damit beim Setzen von DisplayMember und ValueMember kein Fehler auftritt, 
            ' muss die Datasource zunächst geleert werden und der selected index auf -1 gesetzt werden.
            control.DataSource = Nothing
            control.SelectedIndex = -1

            ' Es ist wichtig, dass DisplayMember und ValueMember VOR der DataSource festgelegt werden,
            ' Dadurch ist das Laden der Datasource um einiges SCHNELLER
            If columnCount = 1 Then
                control.DisplayMember = dt.Columns(0).ColumnName
                control.ValueMember = dt.Columns(0).ColumnName
            ElseIf columnCount = 2 Then
                control.DisplayMember = dt.Columns(1).ColumnName
                control.ValueMember = dt.Columns(0).ColumnName
            End If

            ' Als letztes setzen wir die DataSource
            control.DataSource = dt
        End Sub

        Overloads Shared Sub SetDataSource(control As DevExpress.XtraEditors.ListBoxControl, dt As DataTable)
            Dim columnCount As Integer = dt.Columns.Count

            ' Damit beim Setzen von DisplayMember und ValueMember kein Fehler auftritt, 
            ' muss die Datasource zunächst geleert werden und der selected index auf -1 gesetzt werden.
            control.DataSource = Nothing
            control.SelectedIndex = -1

            ' Es ist wichtig, dass DisplayMember und ValueMember VOR der DataSource festgelegt werden,
            ' Dadurch ist das Laden der Datasource um einiges SCHNELLER
            If columnCount = 1 Then
                control.DisplayMember = dt.Columns(0).ColumnName
                control.ValueMember = dt.Columns(0).ColumnName
            ElseIf columnCount = 2 Then
                control.DisplayMember = dt.Columns(1).ColumnName
                control.ValueMember = dt.Columns(0).ColumnName
            End If

            ' Als letztes setzen wir die DataSource
            control.DataSource = dt
        End Sub

        Overloads Shared Sub SetDataSource(control As Windows.Forms.DataGridView, dt As DataTable)
            control.DataSource = dt
        End Sub

    End Class

    Public Structure DynamicValue
        Public StaticList As List(Of String)
        Public DataTable As DataTable
    End Structure

    Public Class Label : Inherits _BaseControl

        Public Shared Sub LoadValue(control As Windows.Forms.Label, recordId As Integer, parentRecordId As Integer, value As String)
            Try
                Dim autoValue = LoadAutoValue(control, recordId, parentRecordId)

                If IsNothing(autoValue) Then
                    Dim ControlId As Integer = DirectCast(control.Tag, ClassControlMetadata).Id
                    Dim SQL = String.Format("SELECT GUID FROM TBPMO_CONTROL_SCREEN WHERE CONTROL_ID = {0} AND SCREEN_ID = {1}", ControlId, CURRENT_SCREEN_ID)
                    Dim ctrl_screen_id = ClassDatabase.Execute_Scalar(SQL, True)
                    If ctrl_screen_id > 0 Then
                        SQL = String.Format("SELECT CAPTION FROM TBPMO_CONTROL_LANGUAGE WHERE CONTROL_SCREEN_ID = {0} AND LANGUAGE_TYPE = '{1}'", ctrl_screen_id, USER_LANGUAGE)
                        Dim labelText As String = ClassDatabase.Execute_Scalar(SQL)
                        control.Text = labelText
                    End If

                Else
                    control.Text = autoValue
                End If
            Catch ex As Exception
                MsgBox("Unexpected Error in LoadValueMain:" & vbNewLine & ex.Message)
                ClassLogger.Add("Unexpected Error in LoadValueMain: " & ex.Message, True)
            End Try

        End Sub

    End Class

    Public Class Checkbox : Inherits _BaseControl

        Public Shared Sub LoadValue(control As Windows.Forms.CheckBox, value As String)
            Try
                Dim result As Boolean = False
                Boolean.TryParse(value, result)
                control.Checked = result
            Catch ex As Exception
                MsgBox("Unexpected Error in LoadValue1:" & vbNewLine & ex.Message)
                ClassLogger.Add("Unexpected Error in LoadValue1: " & ex.Message, True)
            End Try

        End Sub

    End Class

    Public Class RadioButton : Inherits _BaseControl

        Public Shared Sub LoadValue(control As Windows.Forms.RadioButton, value As String)
            Try
                Dim result As Boolean = False
                Boolean.TryParse(value, result)
                control.Checked = result
            Catch ex As Exception
                MsgBox("Unexpected Error in LoadValue2:" & vbNewLine & ex.Message)
                ClassLogger.Add("Unexpected Error in LoadValue2: " & ex.Message, True)
            End Try

        End Sub

    End Class

    Public Class TextBox : Inherits _BaseControl

        Public Shared Sub LoadValue(control As Windows.Forms.TextBox, recordId As Integer, parentRecordId As Integer, value As String)
            Try
                Dim autoValue = LoadAutoValue(control, recordId, parentRecordId)

                If IsNothing(autoValue) Then
                    control.Text = value
                Else
                    control.Text = autoValue
                End If
            Catch ex As Exception
                MsgBox("Unexpected Error in LoadValue3:" & vbNewLine & ex.Message)
                ClassLogger.Add("Unexpected Error in LoadValue3: " & ex.Message, True)
            End Try

        End Sub

    End Class

    Public Class DateTimePicker : Inherits _BaseControl

        Public Shared Sub LoadValue(control As DevExpress.XtraEditors.DateEdit, value As String)
            If String.IsNullOrWhiteSpace(value) Or value = "00:00:00" Then
                control.DateTime = DateTime.MinValue
            Else
                If Not DateTime.TryParse(value, control.DateTime) Then
                    control.DateTime = DateTime.MinValue
                End If
            End If
        End Sub

    End Class

    Public Class Combobox : Inherits _ListControl

        Public Shared Sub LoadValue(control As Windows.Forms.ComboBox, recordId As Integer, parentRecordId As Integer, value As String)
            control.Text = value
        End Sub

        Public Shared Sub LoadList(control As Windows.Forms.ComboBox, formId As Integer, connID As Object, SQLCommand As String)
            Try
                Dim dynamic As DynamicValue = GetDynamicValue(DirectCast(control.Tag, ClassControlMetadata).Id, formId, connID, SQLCommand)

                If dynamic.StaticList IsNot Nothing Then
                    control.DataSource = dynamic.StaticList
                End If

                If dynamic.DataTable IsNot Nothing AndAlso dynamic.DataTable.Rows.Count > 0 Then
                    SetDataSource(control, dynamic.DataTable)
                    CalculateDropdownWidth(control, dynamic.DataTable)
                End If
            Catch ex As Exception
                MsgBox("Error in Combobox.LoadList:" & vbNewLine & ex.Message)
            End Try
        End Sub

        Private Shared Sub CalculateDropdownWidth(control As Windows.Forms.ComboBox, dt As DataTable)
            Try
                Const WIDEST_WIDTH As Integer = 300
                Dim FinalWidth As Integer = WIDEST_WIDTH
                Dim index As Integer = 1
                If dt.Columns.Count = 1 Then
                    index = 0
                End If
                For Each row As DataRow In dt.Rows
                    'Die Breite der Dropdown-List anpassen
                    Using g As Graphics = control.CreateGraphics()
                        Dim valueWidth As Integer = g.MeasureString(row.Item(index).ToString(), control.Font).Width
                        If valueWidth + 30 > FinalWidth Then
                            FinalWidth = valueWidth + 30
                        End If
                        g.Dispose()
                    End Using
                Next

                If FinalWidth > WIDEST_WIDTH Then
                    control.DropDownWidth = Math.Max(FinalWidth, control.Width)
                End If
            Catch ex As Exception
                MsgBox("Error in CalculateDropdownWidth:" & vbNewLine & ex.Message)
            End Try
        End Sub

    End Class

    Public Class CheckedListBox : Inherits _ListControl

        Public Shared Sub LoadValue(control As DevExpress.XtraEditors.CheckedListBoxControl, values As List(Of Object))
            If IsNothing(values) Then
                Exit Sub
            End If

            For Each v As String In values
                Dim pos = control.FindStringExact(v)
                If pos >= 0 Then
                    control.SetItemCheckState(pos, CheckState.Checked)
                End If
            Next
        End Sub

        Public Shared Sub LoadList(control As DevExpress.XtraEditors.CheckedListBoxControl, formId As Integer, conn_Id As Object, SQLCommand As String)
            Try
                Dim dynamic As DynamicValue = GetDynamicValue(DirectCast(control.Tag, ClassControlMetadata).Id, formId, conn_Id, SQLCommand)

                If dynamic.StaticList IsNot Nothing Then
                    control.Items.Clear()
                    For Each item In dynamic.StaticList
                        control.Items.Add(item)
                    Next
                    'control.DataSource = dynamic.StaticList
                End If

                If dynamic.DataTable IsNot Nothing AndAlso dynamic.DataTable.Rows.Count > 0 Then
                    SetDataSource(control, dynamic.DataTable)
                End If

            Catch ex As Exception
                MsgBox("Error in CheckedListBox.LoadList:" & vbNewLine & ex.Message)
            End Try
        End Sub

    End Class

    Public Class ListBox : Inherits _ListControl

        Public Shared Sub LoadValue(control As DevExpress.XtraEditors.ListBoxControl, value As String)
            If IsNothing(value) Then
                Exit Sub
            End If

            control.SelectedIndex = control.FindStringExact(value)
        End Sub

        Public Shared Sub LoadList(control As DevExpress.XtraEditors.ListBoxControl, formId As Integer, ConnId As Object, SQLCommand As String)
            Dim dynamic As DynamicValue = GetDynamicValue(DirectCast(control.Tag, ClassControlMetadata).Id, formId, ConnId, SQLCommand)

            If dynamic.StaticList IsNot Nothing Then
                control.DataSource = dynamic.StaticList
            End If

            If dynamic.DataTable IsNot Nothing AndAlso dynamic.DataTable.Rows.Count > 0 Then
                SetDataSource(control, dynamic.DataTable)
            End If
        End Sub

    End Class

    Public Class DataGridView : Inherits _ListControl

        Public Shared Sub LoadValue(control As Windows.Forms.DataGridView, values As List(Of Object))
            control.Rows.Clear()
            For Each item In values
                control.Rows.Add(item.ToString)
            Next
        End Sub

    End Class

End Namespace
