Imports DevExpress.XtraEditors
Imports DevExpress.XtraLayout
Imports DigitalData.Modules.Logging
Imports DigitalData.Modules.ZooFlow
Imports DigitalData.Modules.Database
Imports DigitalData.Controls.LookupGrid
Imports DevExpress.XtraGrid
Imports System.Windows.Forms
Imports DevExpress.XtraGrid.Views.Grid
Imports DigitalData.Modules.EDMI.API
Imports DigitalData.Modules.Base

Public Class AttributeControls
    Inherits BaseClass

    Private ReadOnly Client As Client
    Private ReadOnly Environment As Environment

    Public Event EditValueChanged As EventHandler

    Public Sub New(pLogConfig As LogConfig, pEnvironment As Environment, pClient As Client)
        MyBase.New(pLogConfig)
        Client = pClient
        Environment = pEnvironment
    End Sub

    Public Function ShouldControlBeEditable(pAttribute As Attribute) As Boolean
        If pAttribute.IsSystem Then
            Return False
        End If

        Return True
    End Function

    Public Async Function GetAttributesForBusinessEntity(EntityId As Long) As Task(Of List(Of Attribute))
        Try
            Dim oSQL = $"SELECT * FROM VWIDB_BE_ATTRIBUTE WHERE BE_ID = {EntityId} AND LANG_CODE = '{Environment.User.Language}'"
            Dim oResult = Await Client.GetDatatableFromIDBAsync(oSQL)

            If oResult.OK = False Then
                Throw New ApplicationException($"Attributes for Business Entity {EntityId} could not be retrieved!")

            ElseIf oResult.Table.Rows.Count = 0 Then
                Throw New ApplicationException($"BusinessEntity {EntityId} does not have any attributes!")

            Else
                Dim oAttributes As New List(Of Attribute)

                For Each oRow As DataRow In oResult.Table.Rows
                    oAttributes.Add(New Attribute() With {
                        .ID = oRow.Item("ATTR_ID"),
                        .Title = oRow.Item("ATTR_TITLE"),
                        .TypeID = oRow.Item("TYPE_ID"),
                        .TypeName = oRow.Item("TYPE_NAME"),
                        .IsSystem = Convert.ToBoolean(oRow.Item("SYS_ATTRIBUTE"))
                    })
                Next

                Return oAttributes
            End If
        Catch ex As Exception
            Logger.Error(ex)
            Return New List(Of Attribute)
        End Try
    End Function

    Public Async Function LoadControlsForAttributes(pObjectId As Long, pAttributes As List(Of Attribute), LayoutRoot As LayoutControlGroup) As Task
        LayoutRoot.Clear()

        For Each oAttribute As Attribute In pAttributes
            Dim oEditable = ShouldControlBeEditable(oAttribute)
            Dim oControl = GetControlForAttribute(oAttribute, Not oEditable)

            ' Add new control
            Dim oItem As LayoutControlItem = LayoutRoot.AddItem()

            oItem.Text = oAttribute.Title
            oItem.Name = oAttribute.Title
            oItem.Control = oControl
        Next

        For Each oItem As LayoutControlItem In LayoutRoot.Items
            If TypeOf oItem.Control Is BaseEdit Then
                Dim oValue = Await GetAttributeValue(oItem.Name, pObjectId)
                Dim oEdit = DirectCast(oItem.Control, BaseEdit)

                oEdit.EditValue = oValue

                AddHandler oEdit.EditValueChanged, Sub() RaiseEvent EditValueChanged(oItem, Nothing)

            ElseIf TypeOf oItem.Control Is GridControl Then
                Dim oValueTable = Await GetAttributeValueAsTable(oItem.Name, pObjectId)
                Dim oGrid = DirectCast(oItem.Control, GridControl)
                oGrid.DataSource = oValueTable


            End If
        Next
    End Function

    Public Async Function GetAttributeValue(AttributeName As String, ObjectId As Long, Optional LanguageCode As String = "de-DE", Optional IsForeign As Boolean = False) As Task(Of Object)
        Dim oIsForeign = IIf(IsForeign, 1, 0)
        Dim oSQL = $"SELECT TERM_VALUE FROM [dbo].[FNIDB_PM_GET_VARIABLE_VALUE] ({ObjectId}, '{AttributeName}', '{LanguageCode}', {oIsForeign})"
        Dim oResult = Await Client.GetScalarValueFromIDBAsync(oSQL)

        Return oResult.Scalar
    End Function

    Public Async Function GetAttributeValueAsTable(AttributeName As String, ObjectId As Long, Optional LanguageCode As String = "de-DE", Optional IsForeign As Boolean = False) As Task(Of DataTable)
        Dim oIsForeign = IIf(IsForeign, 1, 0)
        Dim oSQL = $"SELECT TERM_VALUE FROM [dbo].[FNIDB_PM_GET_VARIABLE_VALUE] ({ObjectId}, '{AttributeName}', '{LanguageCode}', {oIsForeign})"
        Dim oResult = Await Client.GetDatatableFromIDBAsync(oSQL)

        Return oResult.Table
    End Function

    Public Function GetControlForAttribute(pAttribute As Attribute, pIsReadOnly As Boolean) As Control
        Dim oControl As Control

        Select Case pAttribute.TypeName
            Case Attribute.TYPE_BIT
                Dim oCheckboxEdit As New CheckEdit With {
                    .Name = pAttribute.ID,
                    .Text = pAttribute.Title,
                    .[ReadOnly] = pIsReadOnly
                }
                oControl = oCheckboxEdit

            Case Attribute.TYPE_DATE
                Dim oDateEdit As New DateEdit With {
                    .Name = pAttribute.ID,
                    .[ReadOnly] = pIsReadOnly
                }
                oControl = oDateEdit

            Case Attribute.TYPE_BIG_INTEGER
                Dim oTextEdit As New TextEdit With {
                    .Name = pAttribute.ID,
                    .[ReadOnly] = pIsReadOnly
                }
                oControl = oTextEdit

            Case Attribute.TYPE_DECIMAL
                Dim oTextEdit As New TextEdit With {
                    .Name = pAttribute.ID,
                    .[ReadOnly] = pIsReadOnly
                }
                oControl = oTextEdit

            Case Attribute.TYPE_FLOAT
                Dim oTextEdit As New TextEdit With {
                    .Name = pAttribute.ID,
                    .[ReadOnly] = pIsReadOnly
                }
                oControl = oTextEdit

            Case Attribute.TYPE_VECTOR_STRING
                ' Minimum size is picked up by the LayoutControl to determine the grids size
                Dim oGrid As New GridControl With {
                    .Name = pAttribute.ID,
                    .MinimumSize = New System.Drawing.Size(0, 100)
                }

                oGrid.ForceInitialize()

                Dim oView = DirectCast(oGrid.DefaultView, GridView)
                oView.OptionsView.ShowGroupPanel = False
                oView.OptionsView.ShowColumnHeaders = False
                oView.OptionsView.ShowIndicator = False
                oView.OptionsBehavior.ReadOnly = True
                oView.OptionsBehavior.Editable = False
                oControl = oGrid

            Case Else
                Dim oTextEdit As New TextEdit With {
                    .Name = pAttribute.ID,
                    .[ReadOnly] = pIsReadOnly
                }
                oControl = oTextEdit

        End Select

        oControl.Tag = pAttribute

        Return oControl
    End Function
End Class
