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

    End Class

    Public Class _ListControl : Inherits _BaseControl

        Public Shared Function _GetDynamicValue(controlId As Integer, formId As Integer, recordId As Integer, parentRecordId As Integer) As DynamicValue
            Dim returnValue As DynamicValue

            returnValue.StaticList = CheckForStaticList(controlId, recordId)
            returnValue.DataTable = CheckForSqlCommand(controlId, formId, recordId, parentRecordId)

            Return returnValue
        End Function

        Private Shared Function CheckForStaticList(controlId As Integer, recordId 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(";"))
                End If
            Catch ex As Exception
                MsgBox("Error in CheckForStaticList: " & vbNewLine & ex.Message)
                Return Nothing
            End Try
        End Function

        Private Shared Function CheckForSqlCommand(controlId As Integer, formId As Integer, recordId As Integer, parentRecordId As Integer) As DataTable
            Try
                Dim SQL As String = String.Format("SELECT SQL_COMMAND_1 FROM TBPMO_CONTROL WHERE GUID = {0}", controlId)
                Dim SqlCommand As String = ClassDatabase.Execute_Scalar(SQL)

                If SqlCommand Is Nothing Or SqlCommand = String.Empty Then
                    Return Nothing
                End If

                If SqlCommand.Contains("@") Then
                    SqlCommand = ReplaceSqlCommandPlaceholders(SqlCommand, recordId, parentRecordId)
                End If

                Dim CachedDataTable As DataTable = ClassControlValueCache.LoadFromCache(formId, controlId)
                Dim FinalDataTable As DataTable
                If CachedDataTable Is Nothing Then
                    FinalDataTable = ClassDatabase.Return_Datatable(SqlCommand)
                    ClassControlValueCache.SaveToCache(formId, controlId, FinalDataTable)
                Else
                    FinalDataTable = CachedDataTable
                End If

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


    End Class

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

    Public Class Label : Inherits _BaseControl

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

            If SQL = "" Or IsDBNull(SQL) Then
                Return control.Text
            End If

            AutoValue = ClassDatabase.Execute_Scalar(SQL)

            If String.IsNullOrEmpty(AutoValue) Or IsDBNull(AutoValue) Then
                SQL = String.Format("SELECT CONTROL_TEXT FROM TBPMO_CONTROL_SCREEN WHERE CONTROL_ID = {0}", ControlId)
                Dim value = ClassDatabase.Execute_Scalar(SQL)
                Return value
            Else
                Return AutoValue
            End If

        End Function

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

            If IsNothing(autoValue) Then
                control.Text = value
            Else
                control.Text = autoValue
            End If
        End Sub

    End Class

    Public Class Checkbox : Inherits _BaseControl

        Public Shared Sub LoadValue(control As Windows.Forms.CheckBox, value As String)
            Dim result As Boolean = False
            Boolean.TryParse(value, result)
            control.Checked = result
        End Sub

    End Class

    Public Class RadioButton : Inherits _BaseControl

        Public Shared Sub LoadValue(control As Windows.Forms.RadioButton, value As String)
            Dim result As Boolean = False
            Boolean.TryParse(value, result)
            control.Checked = result
        End Sub

    End Class

    Public Class TextBox : Inherits _BaseControl

        Public Shared Sub LoadValue(control As Windows.Forms.TextBox, value As String)
            control.Text = value
        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
                control.DateTime = DateTime.Parse(value)
            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, recordId As Integer, parentRecordId As Integer)
            Try
                Dim dynamic As DynamicValue = _GetDynamicValue(control.Tag, formId, recordId, parentRecordId)

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

                If dynamic.DataTable IsNot Nothing AndAlso dynamic.DataTable.Rows.Count > 0 Then
                    Dim dt As DataTable = dynamic.DataTable
                    Dim columnCount As Integer = dt.Columns.Count

                    Dim sw2 = Stopwatch.StartNew()

                    ' 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

                    ' Die alte Methode:
                    'control.DataSource = dt
                    'If dt.Columns.Count = 1 Then
                    '    control.DisplayMember = dt.Columns(0).ColumnName
                    '    control.ValueMember = dt.Columns(0).ColumnName
                    'ElseIf dt.Columns.Count = 2 Then
                    '    control.DisplayMember = dt.Columns(1).ColumnName
                    '    control.ValueMember = dt.Columns(0).ColumnName
                    'End If

                    sw2.Stop()
                    Console.WriteLine("Assingning the DataSource took {0}ms", sw2.ElapsedMilliseconds)


                    CalculateDropdownWidth(control, dt)
                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)
            Const WIDEST_WIDTH As Integer = 300
            Dim FinalWidth As Integer = WIDEST_WIDTH
            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(1).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
        End Sub

    End Class

    Public Class CheckedListBox : Inherits _ListControl

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

            Dim values() As String = value.Split(";")

            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, recordId As Integer, parentRecordId As Integer)
            Try
                Dim dynamic As DynamicValue = _GetDynamicValue(control.Tag, formId, recordId, parentRecordId)

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

                If dynamic.DataTable IsNot Nothing AndAlso dynamic.DataTable.Rows.Count > 0 Then
                    Dim dt As DataTable = dynamic.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 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, recordId As Integer, parentRecordId As Integer)
            Dim dynamic As DynamicValue = _GetDynamicValue(control.Tag, formId, recordId, parentRecordId)

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

            If dynamic.DataTable IsNot Nothing AndAlso dynamic.DataTable.Rows.Count > 0 Then
                Dim dt As DataTable = dynamic.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 If
        End Sub

    End Class

End Namespace
