Imports System.ComponentModel
Imports DevExpress.XtraSplashScreen
Imports DigitalData.Modules.Database
Imports DigitalData.Modules.Filesystem
Imports DigitalData.Modules.Language.Utils
Imports DigitalData.Modules.Logging
Imports DigitalData.GUIs.ZooFlow.ClassInitLoader
Imports DigitalData.GUIs.ZooFlow.ClassConstants

Public Class ClassInit
    Private _MainForm As frmAdmin
    Private _Logger As Logger

    Public Event Completed As EventHandler

    Public Sub New(LogConfig As LogConfig, ParentForm As frmAdmin)
        _MainForm = ParentForm
        _Logger = LogConfig.GetLogger()
    End Sub

    Public Sub InitializeApplication()
        ' Init Connectivity
        ' - Database / Service / Application Server
        ' (Init Licensing)
        ' Init User
        ' Zeile -> Objekt / NameValue List

        If Not SetupDatabase() Then
            MsgBox("Keine Verbindungs-Informationen hinterlegt. Anwendung wird beendet.", MsgBoxStyle.Critical, _MainForm.Text)
            Application.Exit()
        Else
            Dim oInit As New ClassInitLoader()

            ' === Init Schritte definieren
            oInit.AddStep("Checking connectivity..", AddressOf CheckConnectivity, True)
            oInit.AddStep("Initializing User..", AddressOf InitializeUser, True)
            oInit.AddStep("Loading 3rd-party licenses", AddressOf Initialize3rdParty, False)
            ' === Init Schritte definieren

            AddHandler oInit.ProgressChanged, AddressOf ProgressChanged
            AddHandler oInit.InitCompleted, AddressOf InitCompleted

            oInit.Run()
        End If
    End Sub



    Private Function SetupDatabase() As Boolean
        If My.SystemConfig.ConnectionString = String.Empty Then
            Dim oResult = frmConfigDatabase.ShowDialog()

            If oResult = DialogResult.Cancel Then
                MsgBox("Es wurde keine Datenbank hinterlegt. Die Anwendung wird beendet.")
                Return False
            End If
        End If

        Return True
    End Function

    Private Sub ProgressChanged(sender As Object, Progress As InitProgress)
        SplashScreenManager.Default.SendCommand(frmSplash.SplashScreenCommand.SetProgress, Progress.CurrentPercent)
        SplashScreenManager.Default.SendCommand(frmSplash.SplashScreenCommand.SetActionName, Progress.CurrentStep.Name)
    End Sub

    Private Sub InitCompleted(sender As Object, e As RunWorkerCompletedEventArgs)
        If Not IsNothing(e.Error) Then
            MsgBox("Beim Initialisieren des Programms ist folgender Fehler aufgetreten:" & vbNewLine & vbNewLine & e.Error.Message, MsgBoxStyle.Critical, _MainForm.Text)
            Application.ExitThread()
        Else
            ' Copy back state from MyApplication Helper to My.Application
            Dim oMyApplication As My.MyApplication = DirectCast(e.Result, My.MyApplication)

            My.Application.Settings = oMyApplication.Settings
            My.Application.User = oMyApplication.User
            My.Application.Modules = oMyApplication.Modules
            My.Application.ModulesActive = oMyApplication.ModulesActive

            RaiseEvent Completed(sender, Nothing)
        End If
    End Sub

    Private Sub CheckConnectivity(MyApplication As My.MyApplication)
        Dim oCrypt As New EncryptionLegacy("!35452didalog=")
        Dim oBuilder = My.SystemConfig.GetConnectionStringBuilder(My.SystemConfig.ConnectionString)
        oBuilder.Password = oCrypt.DecryptData(oBuilder.Password)
        Dim oDecryptedConnectionString = oBuilder.ToString

        My.Database = New MSSQLServer(My.LogConfig, oDecryptedConnectionString)

        If My.Database.DBInitialized = False Then
            _Logger.Warn("Datenbank konnte nicht initialisiert werden!")
            Throw New InitException("Datenbank konnte nicht initialisiert werden!")
        End If
    End Sub

    Private Sub Initialize3rdParty(MyApplication As My.MyApplication)
        Try
            Dim oSql = "SELECT * FROM TBCW_CONFIGURATION"
            Dim oDatatable As DataTable = My.Database.GetDatatable(oSql)

            If oDatatable.Rows.Count = 0 Then
                Throw New InitException("Konfiguration konnte nicht geladen werden!")
            End If

            Dim oRow As DataRow = oDatatable.Rows.Item(0)

            MyApplication.Settings.GdPictureKey = NotNull(oRow.Item("GDPICTURE_LICENSE"), String.Empty)
        Catch ex As Exception
            _Logger.Error(ex)
            Throw New InitException("Fehler beim Laden der Konfiguration!")
        End Try
    End Sub

    Private Sub InitializeUser(MyApplication As My.MyApplication)
        Try
            Dim oSql As String = My.Queries.Common.FNDD_MODULE_INIT(Environment.UserName)
            Dim oDatatable As DataTable = My.Database.GetDatatable(oSql)

            If oDatatable.Rows.Count <= 1 Then
                Throw New InitException("Benutzer konnte nicht gefunden werden!")
            End If

            For Each oRow As DataRow In oDatatable.Rows
                Dim oType As String = oRow("TYPE").ToString

                Select Case oType
                    Case "USER"
                        HandleUserInfo(MyApplication, oRow)

                    Case MODULE_CLIPBOARDWATCHER
                        HandleModuleInfo(MyApplication, oType, oRow)

                    Case MODULE_GLOBAL_INDEXER
                        HandleModuleInfo(MyApplication, oType, oRow)
                End Select
            Next
        Catch ex As Exception
            _Logger.Error(ex)
            Throw New InitException("Fehler beim Laden des Benutzers!")
        End Try
    End Sub

    Private Sub HandleUserInfo(MyApplication As My.MyApplication, Row As DataRow)
        Dim oValue As Object = Row.Item("VALUE")
        Dim oName As String = Row.Item("NAME").ToString

        Select Case oName
            Case "USER_ID"
                MyApplication.User.UserId = CInt(oValue)
            Case "USER_PRENAME"
                MyApplication.User.GivenName = NotNull(oValue.ToString, String.Empty)
            Case "USER_SURNAME"
                MyApplication.User.Surname = NotNull(oValue.ToString, String.Empty)
            Case "USER_SHORTNAME"
                MyApplication.User.ShortName = NotNull(oValue.ToString, String.Empty)
            Case "USER_EMAIL"
                MyApplication.User.Email = NotNull(oValue.ToString, String.Empty)
            Case "USER_DATE_FORMAT"
                MyApplication.User.DateFormat = NotNull(oValue.ToString, "dd.MM.yyyy")
            Case "USER_LANGUAGE"
                MyApplication.User.Language = NotNull(oValue.ToString, "de-DE")
        End Select
    End Sub

    Private Sub HandleModuleInfo(MyApplication As My.MyApplication, ModuleName As String, Row As DataRow)
        Dim oValue As Object = Row.Item("VALUE")
        Dim oName As String = Row.Item("NAME").ToString

        If Not MyApplication.Modules.ContainsKey(ModuleName) Then
            MyApplication.Modules.Item(ModuleName) = New DigitalData.Modules.ZooFlow.State.ModuleState()
        End If

        Select Case oName
            Case "MODULE_ACCESS"
                If CBool(oValue) Then
                    SyncLock MyApplication.ModulesActive
                        MyApplication.ModulesActive.Add(ModuleName)
                    End SyncLock
                End If
                MyApplication.Modules.Item(ModuleName).HasAccess = CBool(oValue)

            Case "IS_ADMIN"
                MyApplication.Modules.Item(ModuleName).IsAdmin = CBool(oValue)

            Case "USER_COUNT_LOGGED_IN"
                MyApplication.Modules.Item(ModuleName).LoggedIn = CInt(oValue) + 1

            Case "RESULT"
                Dim oLines = oValue.ToString.Split("|"c)
                _Logger.Debug("Access Result for Module {0}", ModuleName)
                For Each oLine In oLines
                    _Logger.Debug(oLine.Trim)
                Next
        End Select
    End Sub
End Class
