Imports DevExpress.XtraEditors
Imports DevExpress.XtraGrid
Imports DevExpress.XtraLayout
Imports DigitalData.Modules.Logging

Public Class frmObjectEditor
    Private ReadOnly _Datatable As DataTable
    Private _BindingSource As BindingSource
    Private _LayoutConfig As ClassUIConfig.EditFormConfig

    Private _LanguageDatatable As DataTable
    Private _AttributeId As Integer
    Private _Syskey As String

    Private Class ControlMetadata
        Public AttributeId As Integer
        Public DataType As Type
        Public ColumnName As String
    End Class

    Public Sub New(AttributeId As Integer, Syskey As String, Datatable As DataTable)
        ' Dieser Aufruf ist für den Designer erforderlich.
        InitializeComponent()

        ' Fügen Sie Initialisierungen nach dem InitializeComponent()-Aufruf hinzu.
        _Syskey = Syskey
        _AttributeId = AttributeId

        _Datatable = Datatable
        _BindingSource = New BindingSource With {
            .DataSource = _Datatable
        }

        If _Datatable Is Nothing Then
            ShowErrorMessage(New ArgumentNullException("Datatable is empty"))
        End If
    End Sub

    Private Async Sub frmEdit_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Try
            Dim oGridPatcher = New ClassControlPatcher(Of GridControl)(Me)
            oGridPatcher.
                ProcessContainer(AddressOf GridControlDefaults.DefaultGridSettings).
                ProcessContainer(AddressOf GridControlDefaults.ReadOnlyGridSettings)

            labelParentAttributeId.Caption = $"Attribut-ID: {_AttributeId}"
            labelSyskey.Caption = $"Syskey: {_Syskey}"

            GridList.DataSource = _BindingSource

            _LayoutConfig = GetLayoutBySyskey(_Syskey)
            ApplyLayout()

            Await LoadLanguageTableAsync(My.Application.User.Language)
            LoadDetailForm()
        Catch ex As Exception
            ShowErrorMessage(ex)
        End Try
    End Sub

    ''' <summary>
    ''' Applies to currently saved layout to all controls
    ''' </summary>
    Private Sub ApplyLayout()
        SplitContainer.Horizontal = _LayoutConfig.SplitterHorizontal
        SplitContainer.SplitterPosition = _LayoutConfig.SplitterDistance
        BarCheckHorizontalLayout.Checked = _LayoutConfig.SplitterHorizontal
    End Sub

    Private Function GetLayoutBySyskey(Syskey As String) As ClassUIConfig.EditFormConfig
        Dim oConfig = My.UIConfig.EditFormConfigs.Find(Function(c) c.SysKey = Syskey)

        If Not IsNothing(oConfig) Then
            Return oConfig
        Else
            Return New ClassUIConfig.EditFormConfig() With {.SysKey = Syskey}
        End If
    End Function

    Private Sub SaveLayoutBySyskey(Syskey As String, Config As ClassUIConfig.EditFormConfig)
        Dim oIndex = My.UIConfig.EditFormConfigs.FindIndex(Function(c) c.SysKey = Syskey)

        If oIndex >= 0 Then
            My.UIConfig.EditFormConfigs.Item(oIndex) = Config
        Else
            My.UIConfig.EditFormConfigs.Add(Config)
        End If

        My.UIConfigManager.Save()
    End Sub

    Private Sub ResetLayoutBySyskey(Syskey As String)
        Dim oIndex = My.UIConfig.EditFormConfigs.FindIndex(Function(c) c.SysKey = Syskey)
        Dim oDefaultLayout = New ClassUIConfig.EditFormConfig With {.SysKey = Syskey}

        If oIndex >= 0 Then
            My.UIConfig.EditFormConfigs.Item(oIndex) = oDefaultLayout
        End If

        My.UIConfigManager.Save()
    End Sub

    Private Async Function LoadLanguageTableAsync(UserLanguage As String) As Task
        Try
            Dim oSQL = $"SELECT * FROM VWIDB_ATTRIBUTE_LANGUAGE WHERE LANGUAGE_CODE = '{UserLanguage}' AND PARENT_ATTRIBUTE_ID = '{_AttributeId}' ORDER BY ""SEQUENCE"";"

            Await My.Channel.CreateDatabaseRequestAsync("Language Syskey", False)
            Dim oResult = Await My.Channel.ReturnDatatableAsync(oSQL)
            _LanguageDatatable = oResult.Table

            Await My.Channel.CloseDatabaseRequestAsync()
        Catch ex As Exception
            ShowErrorMessage(ex)
        End Try
    End Function

    Private Function GetColumnEditor(Column As DataColumn, AttributeId As Integer)
        Dim oEditor As BaseEdit

        Select Case Column.DataType
            Case GetType(Int64)
                Dim oIntegerEdit = New TextEdit()
                oIntegerEdit.Name = Column.ColumnName
                oIntegerEdit.Properties.Mask.MaskType = Mask.MaskType.Numeric
                oIntegerEdit.Properties.Mask.EditMask = "n"
                oEditor = oIntegerEdit
            Case GetType(DateTime)
                Dim oDateEdit As New DateEdit() With {
                    .Name = Column.ColumnName
                }

                oEditor = oDateEdit
            Case GetType(Boolean)
                Dim oCheckEdit = New CheckEdit() With {
                    .Name = Column.ColumnName
                }

                oCheckEdit.Properties.Caption = Column.ColumnName
                oCheckEdit.Properties.GlyphAlignment = DevExpress.Utils.HorzAlignment.Far

                oEditor = oCheckEdit
            Case Else
                Dim oTextEdit = New MemoEdit() With {
                    .Name = Column.ColumnName
                }

                oEditor = oTextEdit

        End Select


        Dim oMetadata As New ControlMetadata() With {
            .DataType = Column.DataType,
            .ColumnName = Column.ColumnName
        }

        ' Set EditControl Metadata
        If AttributeId = 0 Then
            oMetadata.AttributeId = Nothing
        Else
            oMetadata.AttributeId = AttributeId
        End If

        oEditor.Tag = oMetadata

        Return oEditor
    End Function

    Private Function GetColumnCaption(Column As DataColumn, SequenceId As Integer)
        Dim oRow = GetRowBySequence(SequenceId)
        Dim oCaption = Column.ColumnName

        If oRow IsNot Nothing Then
            oCaption = oRow.Item("LANGUAGE_TERM")
        ElseIf oCaption = ClassConstants.ATTRIBUTE_ID_COLUMN Then
            oCaption = "ID"
        End If

        Return oCaption
    End Function

    Private Function GetRowBySequence(SequenceId As Integer)
        Return _LanguageDatatable.Select($"SEQUENCE = {SequenceId}").FirstOrDefault()
    End Function

    Private Function GetRowItemBySequence(SequenceId As Integer, ColumnName As String)
        Dim oRow = _LanguageDatatable.Select($"SEQUENCE = {SequenceId}").FirstOrDefault()
        Return oRow?.Item(ColumnName)
    End Function

    Private Sub LoadDetailForm()
        ' Counter is used to match SEQUENCE in Attributes 
        ' to column order in the used View (eg. VWIDB_USER)
        Dim oCounter = 0

        For Each oColumn As DataColumn In _Datatable.Columns
            Dim oAttributeId As Integer = GetRowItemBySequence(oCounter, "ATTRIBUTE_ID")
            Dim oCaption = GetColumnCaption(oColumn, oCounter)
            Dim oEditor = GetColumnEditor(oColumn, oAttributeId)

            ' Setup Databinding for editor
            If oColumn.DataType = GetType(Boolean) Then
                oEditor.DataBindings.Add(New Binding("Checked", _BindingSource, oColumn.ColumnName))
            Else
                oEditor.DataBindings.Add(New Binding("Text", _BindingSource, oColumn.ColumnName))
            End If

            ' Add Control to Layout
            LayoutGroup.AddItem(oCaption, oEditor)

            ' Set Column Captions
            ViewList.Columns.Item(oColumn.ColumnName).Caption = oCaption

            oCounter = oCounter + 1
        Next

        ' General Layout Tweaks
        LayoutGroup.AddItem(New EmptySpaceItem())
        LayoutGroup.LayoutMode = Utils.LayoutMode.Flow
    End Sub

    Public Sub SaveRecord()
        _BindingSource.EndEdit()

        Dim oChanges As DataTable = _Datatable.GetChanges()
        Dim oChangedRow As DataRow = oChanges.Rows.Item(0)

        For Each oColumn As DataColumn In oChanges.Columns
            Dim oAttributeId = (From oItem As LayoutControlItem In LayoutGroup.Items
                                Where oItem.Control.Name = oColumn.ColumnName
                                Select DirectCast(oItem.Control.Tag, ControlMetadata).AttributeId).FirstOrDefault()

            Dim oValue = oChangedRow.Item(oColumn.ColumnName)
            MsgBox($"Saving Value {oValue} for Attribute {oAttributeId}")
        Next
    End Sub


    Private Sub SplitContainerControl1_SplitterPositionChanged(sender As Object, e As EventArgs) Handles SplitContainer.SplitterPositionChanged
        _LayoutConfig.SplitterDistance = SplitContainer.SplitterPosition
        SaveLayoutBySyskey(_Syskey, _LayoutConfig)
    End Sub

    Private Sub BarButtonSave_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles BarButtonSave.ItemClick
        SaveRecord()
    End Sub

    Private Sub BarCheckHorizontalLayout_CheckedChanged(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles BarCheckHorizontalLayout.CheckedChanged
        SplitContainer.Horizontal = BarCheckHorizontalLayout.Checked
        _LayoutConfig.SplitterHorizontal = BarCheckHorizontalLayout.Checked
        SaveLayoutBySyskey(_Syskey, _LayoutConfig)
    End Sub

    Private Sub BarButtonResetLayout_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles BarButtonResetLayout.ItemClick
        Dim oDefaultLayout = New ClassUIConfig.EditFormConfig With {.SysKey = _Syskey}
        SaveLayoutBySyskey(_Syskey, oDefaultLayout)
        _LayoutConfig = oDefaultLayout
        ApplyLayout()
    End Sub

    Private Sub ViewList_Layout(sender As Object, e As EventArgs) Handles ViewList.Layout

    End Sub
End Class