Imports System.IO
Imports DigitalData.Modules.Database
Imports DigitalData.Modules.Language
Imports DigitalData.Modules.Logging
Imports DigitalData.Modules.Patterns
Imports DigitalData.Modules.ZooFlow.State
Imports DigitalData.Services.EDMIService.IDB
Imports DigitalData.Services.EDMIService.Methods.IDB

Namespace Methods.GlobalIndexer.ImportFile.Steps
    Public Class AutomaticIndexing
        Inherits BaseClass

        Private ReadOnly GlobalState As GlobalState
        Private ReadOnly AutomaticIndexes As List(Of AutomaticIndex)
        Private ReadOnly Patterns As Patterns2
        Private ReadOnly Helpers As Helpers
        Private ReadOnly Database As MSSQLServer

        Public Sub New(pLogConfig As LogConfig, pDatabase As MSSQLServer, pAutomaticIndexes As List(Of AutomaticIndex), pGlobalState As GlobalState)
            MyBase.New(pLogConfig)
            Database = pDatabase
            GlobalState = pGlobalState
            AutomaticIndexes = pAutomaticIndexes
            Patterns = New Patterns2(pLogConfig)
            Helpers = New Helpers(pLogConfig, pDatabase)

            Logger.Info("Initializing Automatic Indexing")
        End Sub

        ''' <summary>
        ''' Generates a new list of Auto Attributes from the Auto Index configuration and External Data (like User, FileInfo and UserAttributes)
        ''' </summary>
        ''' <returns>A new list of Automatic Attributes. This list may be empty.</returns>
        Public Function ApplyAutomaticeAttributes(pUserAttributes As List(Of UserAttributeValue), pFileInfo As FileInfo, pUserState As UserState) As List(Of UserAttributeValue)
            Logger.Debug("Start of Method [ApplyAutomaticAttributes]")

            If AutomaticIndexes Is Nothing OrElse AutomaticIndexes.Count = 0 Then
                Logger.Warn("No Automatix Indexes supplied. Exiting.")
                Return New List(Of UserAttributeValue)
            End If

            Logger.Info("Processing [{0}] automatic indexes", AutomaticIndexes.Count)
            Dim oUserAttributes As List(Of UserAttributeValue) = pUserAttributes
            Dim oAutoAttributes As New List(Of UserAttributeValue)

            For Each oAutomaticIndex In AutomaticIndexes
                ' We add oAttributes from the previous run into the current run so it is in theory possible to reference
                ' automatic attributes which have been set just before.
                Dim oAttribute = ApplyAutomaticIndex(oAutomaticIndex, pFileInfo, pUserState, oUserAttributes, oAutoAttributes)

                If oAttribute IsNot Nothing Then
                    Logger.Debug("Adding Attribute [{0}]", oAttribute)
                    oAutoAttributes.Add(oAttribute)
                End If
            Next

            Return oAutoAttributes
        End Function

        Private Function ApplyAutomaticIndex(pAutomaticIndex As AutomaticIndex,
                                             pFileInfo As FileInfo,
                                             pUserState As UserState,
                                             pAttributes As List(Of UserAttributeValue),
                                             pAutoAttributes As List(Of UserAttributeValue)) As UserAttributeValue
            Try
                Dim oAttributeDict = Helpers.UserAttributesToDictionary(pAttributes)
                Dim oAutoAttributeDict = Helpers.UserAttributesToDictionary(pAutoAttributes)

                Logger.Info("Applying Automatic Index [{0}]", pAutomaticIndex.Name)

                Dim oHasSqlCommand As Boolean = pAutomaticIndex.HasSqlCommand

                Logger.Debug("Index has SQLCommand: [{0}]", oHasSqlCommand)

                ' If there is no SQL command, we use the Value property and replace all placeholders in it.
                If oHasSqlCommand = False Then
                    Dim oResult As String = Helpers.GetPlaceholderValue(
                        pAutomaticIndex.Value, pFileInfo, pUserState, oAttributeDict, oAutoAttributeDict)

                    Return New UserAttributeValue With {
                        .Values = New List(Of String) From {oResult},
                        .Name = pAutomaticIndex.Name,
                        .Id = pAutomaticIndex.Id
                    }
                End If

                ' Otherwise we will replace placeholders in the SQL command and then execute it
                Dim oConnectionString As String = GlobalState.GetConnectionString(pAutomaticIndex.SQLConnectionId)
                Dim oFinalSQLCommand = pAutomaticIndex.SQLCommand

                ' TODO: Dont show the unmasked conn string
                Logger.Debug("SQL Connection String is: [{0}]", oConnectionString)
                Logger.Debug("SQL Command is: [{0}]", oFinalSQLCommand)

                oFinalSQLCommand = Helpers.GetPlaceholderValue(
                    oFinalSQLCommand, pFileInfo, pUserState, oAttributeDict, oAutoAttributeDict)

                ' Now we have a SQL command which only contains vector placeholders
                ' Next, we execute the command to get our result
                Dim oTable = Database.GetDatatableWithConnection(oFinalSQLCommand, oConnectionString)

                If oTable Is Nothing Then
                    Logger.Warn("SQL for Automatic Index [{0}] returned an error. Exiting.")
                    Return Nothing
                End If

                Dim oValues As New List(Of String)

                For Each oRow As DataRow In oTable.Rows
                    Try
                        Dim oValue As String = oRow.ItemArray(0)?.ToString()
                        If oValue IsNot Nothing AndAlso oValue.Length > 0 Then
                            oValues.Add(oValue)
                        End If
                    Catch ex As Exception
                        Logger.Warn("Error while parsing the Result from SQL Command. Skipping.")
                        Logger.Error(ex)
                    End Try
                Next

                Logger.Info("Value for Automatic Index [{0}] is [{1}]", pAutomaticIndex.Name, oValues.FirstOrDefault)

                ' TODO: Return multiple values
                Return New UserAttributeValue With {
                    .Values = oValues,
                    .Name = pAutomaticIndex.Name,
                    .Id = pAutomaticIndex.Id
                }
            Catch ex As Exception
                Logger.Warn("Automatic Indexing for index failed.")
                Logger.Error(ex)

                Return Nothing
            End Try
        End Function


    End Class

End Namespace