Imports System.Windows.Forms
Imports DevExpress.XtraEditors.Repository
Imports DigitalData.GUIs.Common.Base
Imports DigitalData.Modules.EDMI.API
Imports DigitalData.Modules.Logging
Imports DigitalData.Modules.Language
Imports DigitalData.Modules.ZooFlow

Public Class ctrlObjectPropertyDialog
    Implements IBaseForm

    Private Property LogConfig As LogConfig Implements IBaseForm.LogConfig
    Private Property Logger As Logger Implements IBaseForm.Logger
    Private Property ErrorHandler As BaseErrorHandler Implements IBaseForm.ErrorHandler
    Private Property ControlManager As AttributeControls
    Private Property Client As Client
    Private Property Environment As Environment
    Private Property ObjectId As Long

    Private ReadOnly Changes As New Dictionary(Of String, Object)
    Private Property Loading As Boolean = False

    Public Sub Initialize(pLogConfig As LogConfig, pHostForm As Form, pClient As Client, pEnv As Environment)
        LogConfig = pLogConfig
        Logger = pLogConfig.GetLogger()
        ErrorHandler = New BaseErrorHandler(pLogConfig, pHostForm)
        ControlManager = New AttributeControls(pLogConfig, pEnv, pClient)
        Client = pClient
        Environment = pEnv
    End Sub

    Public Async Function LoadObject(pObjectId As Long) As Task(Of Boolean)
        ' Load Business Entities
        Dim oEntityIds = Await GetBusinessEntitiesForObjectId(pObjectId)
        Dim oActiveEntity = oEntityIds.FirstOrDefault()

        Dim oCombobox As RepositoryItemComboBox = DirectCast(cmbEntityId.Edit, RepositoryItemComboBox)
        oCombobox.Items.Clear()
        oCombobox.Items.AddRange(oEntityIds)
        cmbEntityId.EditValue = oEntityIds.First()

        Return Await LoadObject(pObjectId, oActiveEntity)
    End Function

    Public Async Function LoadObject(pObjectId As Long, pEntityId As Long) As Task(Of Boolean)
        Loading = True
        Try
            ObjectId = pObjectId

            ' Load History of attribute value changes
            Dim oAttributeHistoryTable = Await GetValueHistoryForObjectId(pObjectId)
            ShowAttributeHistory(oAttributeHistoryTable)

            ' Load History of object state changes
            Dim oObjectHistoryTable = Await GetObjectHistoryForObjectId(pObjectId)
            ShowObjectHistory(oObjectHistoryTable)

            ' Load Object Properties
            Dim oObjectProperties = Await GetPropertiesForObjectId(ObjectId)
            ShowObjectProperties(oObjectProperties)

            ' Load Attribute controls and values
            Dim oAttributes = Await ControlManager.GetAttributesForBusinessEntity(cmbEntityId.EditValue)
            Await ControlManager.LoadControlsForAttributes(ObjectId, oAttributes, Root)
        Catch ex As Exception
            Logger.Error(ex)
        Finally
            Loading = False
        End Try
    End Function

    Private Function ShowAttributeHistory(pDatatable As DataTable) As Boolean
        Try
            GridValueHistory.DataSource = pDatatable

            Return True
        Catch ex As Exception
            Logger.Error(ex)
            Return False
        End Try
    End Function

    Private Function ShowObjectHistory(pDatatable As DataTable) As Boolean
        Try
            GridObjectHistory.DataSource = pDatatable

            Return True
        Catch ex As Exception
            Logger.Error(ex)
            Return False
        End Try
    End Function

    Private Function ShowObjectProperties(pDatatable As DataTable) As Boolean
        Try
            Dim oRow As DataRow = pDatatable.Rows.Item(0)
            txtObjectId.Text = oRow.Item("IDB_OBJ_ID")
            txtCreatedWhen.Text = oRow.Item("ADDED_WHEN")
            txtCreatedWho.Text = oRow.Item("ADDED_WHO")
            txtChangedWhen.Text = Utils.NotNull(oRow.Item("CHANGED_WHEN"), String.Empty)
            txtChangedWho.Text = Utils.NotNull(oRow.Item("CHANGED_WHO"), String.Empty)

            lbLifecycleStart.Text = DirectCast(oRow.Item("ADDED_WHEN"), Date).ToShortDateString
            lbLifecycleEnd.Text = Date.MaxValue.ToShortDateString
            progressLifecycle.Position = 30

            Return True
        Catch ex As Exception
            Logger.Error(ex)
            Return False
        End Try
    End Function

    Private Async Function GetBusinessEntitiesForObjectId(ObjectId As Long) As Task(Of List(Of Long))
        Try
            Dim oSQL = $"SELECT BE_ID FROM TBIDB_OBJECT_BE WHERE IDB_OBJ_ID = {ObjectId}"
            Dim oResult = Await Client.GetDatatableFromIDBAsync(oSQL)

            If oResult.OK = False Then
                Throw New ApplicationException($"Business Entities could not be retrieved!")

            ElseIf oResult.Table.Rows.Count = 0 Then
                Throw New ApplicationException($"ObjectId {ObjectId} is not assigned to any business entity!")

            Else
                Dim oEntities As New List(Of Long)

                For Each oRow In oResult.Table.Rows
                    oEntities.Add(oRow.item("BE_ID"))
                Next

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

    Private Async Function GetValueHistoryForObjectId(ObjectId As Long) As Task(Of DataTable)
        Dim oSQL As String = $"
            SELECT * FROM VWIDB_CHANGE_LOG 
            WHERE IDB_OBJ_ID = {ObjectId}
            ORDER BY ChangeID DESC
        "
        Dim oResult = Await Client.GetDatatableFromIDBAsync(oSQL)

        Return oResult.Table
    End Function

    Private Async Function GetObjectHistoryForObjectId(ObjectId As Long) As Task(Of DataTable)
        Dim oSQL As String = $"
            SELECT * FROM VWIDB_DOC_STATES 
            WHERE IDB_OBJ_ID = {ObjectId} AND LANG_CODE = '{Environment.User.Language}'
            ORDER BY ADDED_WHEN DESC
        "
        Dim oResult = Await Client.GetDatatableFromIDBAsync(oSQL)

        Return oResult.Table
    End Function

    Private Async Function GetPropertiesForObjectId(ObjectId As Long) As Task(Of DataTable)
        Dim oSQL As String = $"SELECT * FROM TBIDB_OBJECT WHERE IDB_OBJ_ID = {ObjectId}"
        Dim oResult = Await Client.GetDatatableFromIDBAsync(oSQL)

        Return oResult.Table
    End Function

    Private Async Sub Load_Attributes(pObject As Long, pBusinessEntityId As Long)
        Try
            Dim oAttributes = Await ControlManager.GetAttributesForBusinessEntity(pBusinessEntityId)

            If oAttributes.Count = 0 Then
                MsgBox($"Es konnten keine Attribute für das Objekt '{pObject}' geladen werden!", MsgBoxStyle.Critical, Text)
            End If

            Await ControlManager.LoadControlsForAttributes(pObject, oAttributes, Root)
        Catch ex As Exception
            Logger.Error(ex)
        End Try
    End Sub

    Private Async Sub cmbEntityId_EditValueChanged(sender As Object, e As EventArgs) Handles cmbEntityId.EditValueChanged
        Dim oEntityId As Long

        If Integer.TryParse(cmbEntityId.EditValue, oEntityId) AndAlso Loading = False Then
            LoadObject(ObjectId, oEntityId)
        End If
    End Sub
End Class
