Imports DigitalData.Modules.Database
Imports DigitalData.Modules.Database.MSSQLServer
Imports DigitalData.Modules.Language
Imports DigitalData.Modules.Logging
Imports DigitalData.Modules.EDMI.API.Client
Imports System.Data.SqlClient
Imports System.IO
Imports DigitalData.Modules.ZooFlow.State
Imports DigitalData.Modules.Patterns
Imports DigitalData.Services.EDMIService.Methods.IDB

Namespace IDB
    Public Class Helpers
        Inherits BaseClass

        Private ReadOnly Patterns As Patterns2
        Private ReadOnly Database As MSSQLServer

        Public Sub New(pLogConfig As LogConfig, pMSSQLServer As MSSQLServer)
            MyBase.New(pLogConfig)
            Patterns = New Patterns2(pLogConfig)
            Database = pMSSQLServer
        End Sub

        Public Function GetPlaceholderValue(pValue As String,
                                            pFileInfo As FileInfo,
                                            pUserState As UserState,
                                            pUserAttributes As Dictionary(Of String, List(Of String)),
                                            pAutoAttributes As Dictionary(Of String, List(Of String))) As String
            Dim oResult As String = pValue

            oResult = Patterns.ReplaceInternalValues(oResult)
            oResult = Patterns.ReplaceFileValues(oResult, pFileInfo)
            oResult = Patterns.ReplaceUserValues(oResult, pUserState)
            oResult = Patterns.ReplaceGlobixValues(oResult, pUserAttributes, pAutoAttributes)

            Return oResult
        End Function

        Public Function UserAttributesToDictionary(pUserAttributes As List(Of UserAttributeValue)) As Dictionary(Of String, List(Of String))
            If pUserAttributes Is Nothing OrElse pUserAttributes.Count = 0 Then
                Return New Dictionary(Of String, List(Of String))
            End If

            Return pUserAttributes.ToDictionary(
               Function(attr) attr.Name,
               Function(attr) attr.Values)
        End Function

        Public Function TestObjectIdExists(pObjectId As Long, Optional ByRef IsDeleted As Boolean = False, Optional ByRef IsActive As Boolean = False) As Boolean
            Try
                Dim oSQL As String = $"SELECT IDB_OBJ_ID, ACTIVE, DELETED FROM TBIDB_OBJECT WHERE IDB_OBJ_ID = {pObjectId}"
                Dim oTable As DataTable = Database.GetDatatable(oSQL)

                If IsNothing(oTable) OrElse oTable.Rows.Count = 0 Then
                    Logger.Warn("ObjectId {0} does not exist")
                    Return False
                End If

                Dim oRow As DataRow = oTable.Rows.Item(0)
                Dim oActive = Utils.NotNull(oRow.Item("ACTIVE"), False)
                Dim oDeleted = Utils.NotNull(oRow.Item("DELETED"), False)

                IsDeleted = oDeleted
                IsActive = oActive

                Return True

            Catch ex As Exception
                Logger.Error(ex)
                Return False

            End Try
        End Function

        Public Function TestFileChecksumExists(pChecksum As String) As Long
            Try
                Dim oChecksumSQL = $"SELECT IDB_OBJ_ID FROM TBIDB_FILE_OBJECT WHERE FILE_HASH = '{pChecksum}'"
                Dim oExistingObjectId As Long = Database.GetScalarValue(oChecksumSQL)

                If oExistingObjectId > 0 Then
                    Logger.Info("Returning early with ObjectId [{0}] because Checksum [{1}] already exists.", oExistingObjectId, pChecksum)
                    Return oExistingObjectId
                End If

                Return Nothing

            Catch ex As Exception
                Logger.Error(ex)
                Return Nothing

            End Try
        End Function

        Public Function NewObjectId(pKindType As String, pBusinessEntity As String, pWho As String) As Long
            Try
                Dim oNewObjectIdSQL = $"DECLARE @NEW_IDB_OBJ_ID BIGINT
                            EXEC PRIDB_NEW_OBJECT '{pKindType}','{pWho}','{pBusinessEntity}',0, @IDB_OBJ_ID = @NEW_IDB_OBJ_ID OUTPUT;
                            SELECT @NEW_IDB_OBJ_ID"
                Dim oObjectId As Long = Database.GetScalarValue(oNewObjectIdSQL)

                Logger.Info("New Object with Id [{0}] created!", oObjectId)

                If IsNothing(oObjectId) Then
                    LogAndThrow("Could not create new ObjectId!")
                End If

                Return oObjectId
            Catch ex As Exception
                Logger.Error(ex)
                Return Nothing
            End Try
        End Function

        Public Function NewObjectIdWithTransaction(pKindType As String, pBusinessEntity As String, pWho As String, pConnection As SqlConnection, pTransaction As SqlTransaction) As Long
            Try
                Dim oNewObjectIdSQL = $"DECLARE @NEW_IDB_OBJ_ID BIGINT
                            EXEC PRIDB_NEW_OBJECT '{pKindType}','{pWho}','{pBusinessEntity}',0, @IDB_OBJ_ID = @NEW_IDB_OBJ_ID OUTPUT;
                            SELECT @NEW_IDB_OBJ_ID"
                Dim oObjectId As Long = Database.GetScalarValueWithConnectionObject(oNewObjectIdSQL,
                                                                                    pConnection,
                                                                                    TransactionMode.ExternalTransaction,
                                                                                    pTransaction)

                Logger.Info("New Object with Id [{0}] created!", oObjectId)

                If IsNothing(oObjectId) Then
                    LogAndThrow("Could not create new ObjectId!")
                End If

                Return oObjectId
            Catch ex As Exception
                Logger.Error(ex)
                Return Nothing
            End Try
        End Function

        Public Function GetObject(pObjectId As Long) As IDBObject
            Try
                Dim oGetObjectSQL = $"SELECT * FROM VWIDB_OBJECT WHERE IDB_OBJ_ID = {pObjectId}"
                Dim oRow As DataTable = Database.GetDatatable(oGetObjectSQL)

                If oRow Is Nothing Then
                    Logger.Warn("Object with Id [{0}] not found.", pObjectId)
                    Return Nothing

                End If

                'TODO: Return object data

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

        'Public Function GetAttributesForObject(pObjectId As Long, pLanguage As String) As List(Of ObjectAttribute)
        '    Dim oAttributes As New List(Of ObjectAttribute)

        '    Try
        '        Dim oTable As DataTable = Database.GetDatatable($"EXEC [PRIDB_GET_VALUE_DT] {pObjectId}, '{pLanguage}'")
        '        If oTable Is Nothing OrElse oTable.Rows.Count = 0 Then
        '            Return Nothing
        '        End If

        '        For Each oRow As DataRow In oTable.Rows
        '            Dim oAttribute As New ObjectAttribute With {
        '                .Id = oRow.Item("AttributeId"),
        '                .Title = oRow.Item("AttributeTitle"),
        '                .Type = oRow.Item("AttributeType"),
        '                .ValueBigInt = Utils.NotNull(oRow.Item("ValueBigInt"), Nothing),
        '                .ValueDate = Utils.NotNull(oRow.Item("ValueDate"), Nothing),
        '                .ValueDecimal = Utils.NotNull(oRow.Item("ValueDecimal"), Nothing),
        '                .ValueText = Utils.NotNull(oRow.Item("ValueText"), Nothing)
        '            }

        '            oAttributes.Add(oAttribute)
        '        Next

        '        Return oAttributes
        '    Catch ex As Exception
        '        Logger.Error(ex)
        '        Return Nothing
        '    End Try
        'End Function

        Public Function SetAttributeValue(pConnection As SqlConnection, pTransaction As SqlTransaction, pObjectId As Long, pAttributeName As String, pValue As String, pLanguage As String, pWho As String) As Boolean
            Dim oSql = $"
                DECLARE @NEW_OBJ_MD_ID BIGINT
                EXEC PRIDB_NEW_OBJ_DATA {pObjectId}, '{pAttributeName}', '{pWho}', '{pValue}', '{pLanguage}', 0, @OMD_ID = @NEW_OBJ_MD_ID OUTPUT"

            If Database.ExecuteNonQueryWithConnectionObject(oSql, pConnection, MSSQLServer.TransactionMode.ExternalTransaction, pTransaction) = False Then
                Logger.Warn("Error while setting attribute value.")
                Return False
            End If

            Return True
        End Function
    End Class

End Namespace