Imports System.Drawing
Imports System.Windows.Forms
Imports DevExpress.XtraEditors
Imports DigitalData.GUIs.Common
Imports DigitalData.Modules.Logging
Imports DigitalData.Modules.Windows
Imports DigitalData.Modules.Language
Imports DigitalData.Modules.ZooFlow
Imports DigitalData.Modules.ZooFlow.Params

''' <summary>
''' 
''' Selfcontained:
''' - Config (Location of Window)
''' 
''' Environment:
''' - Pattern Replacement Values
''' - User Info (isAdmin, etc)
''' - License Info?
''' - ConnectionString
''' 
''' Parameters:
''' - Matching Profiles as List Of ProfileData
''' - Clipboard Content as String
''' </summary>
Public Class frmMatch
    Private _LogConfig As LogConfig
    Private _Logger As Logger
    Private _Environment As Environment
    Private _Params As ClipboardWatcherParams

    Private PrimaryFont As New Font("Segoe UI", 12, FontStyle.Bold)
    Private SecondaryFont As New Font("Segoe UI", 10)

    Private OpenForms As New List(Of IResultForm)
    Private ShouldHideInitially As Boolean = False

    Private Const NO_COUNT_SQL As Integer = 99998
    Private Const INVALID_COUNT_SQL As Integer = 99999

    Private Enum ProfileType
        ANY = 0
        DOCS_ONLY = 1
        DATA_ONLY = 2
    End Enum

    Public Sub New(LogConfig As LogConfig, Environment As Environment, Params As ClipboardWatcherParams)
        ' Dieser Aufruf ist für den Designer erforderlich.
        InitializeComponent()

        ' Fügen Sie Initialisierungen nach dem InitializeComponent()-Aufruf hinzu.
        _LogConfig = LogConfig
        _Logger = LogConfig.GetLogger()
        _Environment = Environment
        _Params = Params
    End Sub

    Private Async Sub frmMatch_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim oCreatedTiles = CreateTiles()

        If oCreatedTiles = -1 Then
            Exit Sub
        End If

        If oCreatedTiles = 0 Then
            _Logger.Warn("No Tiles Created: No Results found for ""{0}""", _Params.ClipboardContents)
            Close()
        End If

        Dim oMatchString = IIf(oCreatedTiles = 1, "1 Profil", $"{oCreatedTiles} Profile")
        Label1.Text = String.Format(Label1.Text, oMatchString, _Params.ClipboardContents)
        _Logger.Debug($"Created Tiles: {oCreatedTiles} ")
        If oCreatedTiles = 1 Then

            Dim oProfile As ProfileData = _Params.MatchingProfiles.First()
            Dim oProfileSearch As New ProfileSearches(_LogConfig, _Environment, _Params)

            If oProfile.CountDocs > 0 And oProfile.CountData = 0 Then
                _Logger.Debug($"ONLY Docs")
                'ONLY DOCS AND NÒ DATA
                Dim oSearches = Await oProfileSearch.LoadDocumentSearchesAsync(oProfile.Guid)
                OpenDocumentResults(oProfile, oSearches)
                Hide()
            ElseIf oProfile.CountDocs > 0 And oProfile.CountData > 0 Then
                _Logger.Debug($"Docs AND Data")
            ElseIf oProfile.CountDocs = 0 And oProfile.CountData > 0 Then
                _Logger.Debug($"ONLY Data")
                Dim oSearches = Await oProfileSearch.LoadDataSearchesAsync(oProfile.Guid)
                OpenDataResults(oProfile, oSearches)
                Hide()
            End If
        End If
    End Sub

    Private Sub frmMatch_Activated(sender As Object, e As EventArgs) Handles Me.Activated
        TopMost = True
    End Sub

    Function CreateTiles() As Integer
        Try
            Dim oCreatedTiles As Integer = 0
            Dim oDocumentGroup = TileControlMatch.Groups.Item("TileGroupDocuments")
            Dim oDataGroup = TileControlMatch.Groups.Item("TileGroupData")
            Dim oDataDocumentsGroup = TileControlMatch.Groups.Item("TileGroupDocumentsData")

            oDocumentGroup.Items.Clear()
            oDataGroup.Items.Clear()

            For Each oProfile As ProfileData In _Params.MatchingProfiles
                'TODO: Add Support for Combined Result Lists
                'If oProfile.ProfileType = ProfileType.ANY Then
                '    If oProfile.CountData > 0 And oProfile.CountDocs > 0 Then
                '        Dim oCountText = oProfile.CountData + oProfile.CountDocs
                '        Dim oItem = CreateTile(oProfile, $"{oCountText} Ergebnisse")
                '        oDataDocumentsGroup.Items.Add(oItem)
                '        oCreatedTiles += 1
                '    End If
                'End If

                If oProfile.ProfileType = ProfileType.ANY Or oProfile.ProfileType = ProfileType.DOCS_ONLY Then
                    _Logger.Debug("Docs only or ProfileTypeAny")
                    If oProfile.CountDocs > 0 Then
                        Dim oItem = CreateTile(oProfile, $"{oProfile.CountDocs} Dateien")
                        oDocumentGroup.Items.Add(oItem)
                        oCreatedTiles += 1
                    Else
                        _Logger.Debug("NO Doc-Results!")
                    End If
                End If

                If oProfile.ProfileType = ProfileType.ANY Or oProfile.ProfileType = ProfileType.DATA_ONLY Then
                    If oProfile.CountData > 0 Then
                        Dim oItem = CreateTile(oProfile, $"{oProfile.CountData} Datensätze")
                        oDataGroup.Items.Add(oItem)
                        oCreatedTiles += 1
                    Else
                        _Logger.Debug("NO Data-Results!")
                    End If
                End If
            Next

            Return oCreatedTiles
        Catch ex As Exception
            _Logger.Error(ex)
            MsgBox("Error while creating profile tiles!" & vbNewLine & ex.Message)
            Return -1
        End Try
    End Function

    Private Function CreateTile(Profile As ProfileData, CountText As String) As TileItem
        Dim oItem As New TileItem() With {.Tag = Profile.Guid}
        oItem.Elements.Clear()

        Dim oNameElement = New TileItemElement With {
            .Text = Profile.Name,
            .TextAlignment = TileItemContentAlignment.TopLeft
        }
        oNameElement.Appearance.Normal.Font = PrimaryFont
        oItem.Elements.Add(oNameElement)

        Dim oCommentElement = New TileItemElement With {
            .Text = Profile.Comment,
            .TextAlignment = TileItemContentAlignment.MiddleLeft
        }
        oCommentElement.Appearance.Normal.Font = SecondaryFont
        oItem.Elements.Add(oCommentElement)

        Dim oCountElement = New TileItemElement With {
            .Text = GetCountText(Profile, CountText),
            .TextAlignment = TileItemContentAlignment.BottomRight
        }
        oCountElement.Appearance.Normal.Font = SecondaryFont
        oItem.Elements.Add(oCountElement)

        Return oItem
    End Function

    Private Function GetCountText(Profile As ProfileData, CountText As String) As String
        Dim oText As String = "No implemented"

        If Profile.CountData = INVALID_COUNT_SQL Then
            oText = "Invalid SQL!"
        ElseIf Profile.CountData = NO_COUNT_SQL Then
            oText = "No SQL!"
        Else
            oText = CountText
        End If

        If Profile.CountDocs = INVALID_COUNT_SQL Then
            oText = "Invalid SQL!"
        ElseIf Profile.CountDocs = NO_COUNT_SQL Then
            oText = "No SQL!"
        Else
            oText = CountText
        End If

        Return oText
    End Function

    Private Sub Label2_Click(sender As Object, e As EventArgs) Handles Label2.Click
        Dim oForm As New frmTreeView(_Params.MatchTreeView.Nodes) With {
            .StartPosition = FormStartPosition.CenterScreen
        }
        oForm.ShowDialog()
    End Sub

    Private Async Sub TileControlMatch_ItemClick(sender As Object, e As TileItemEventArgs) Handles TileControlMatch.ItemClick
        Dim oItem As TileItem = e.Item
        Dim oProfileId As Integer = oItem.Tag

        Dim oProfileSearch As New ProfileSearches(_LogConfig, _Environment, _Params)
        Dim oProfile As ProfileData = _Params.MatchingProfiles.
            Where(Function(p) p.Guid = oProfileId).
            ToList().
            First()

        Select Case oItem.Group.Name
            Case TileGroupData.Name
                Dim oSearches = Await oProfileSearch.LoadDataSearchesAsync(oProfileId)
                OpenDataResults(oProfile, oSearches)

            Case TileGroupDocuments.Name
                Dim oSearches = Await oProfileSearch.LoadDocumentSearchesAsync(oProfileId)
                OpenDocumentResults(oProfile, oSearches)

            Case Else
                ' TODO: Load combined results
                'OpenResultForms(oProfileId, ProfileType.ANY)
        End Select

        Hide()
    End Sub

    Private Sub OpenDocumentResults(Profile As ProfileData, Searches As List(Of ProfileSearches.Search))
        Dim oNameSlug = Language.Utils.ConvertTextToSlug(Profile.Name)
        Dim oSearchGuids = Searches.Select(Function(s) s.Guid).ToArray
        Dim oWindowGuid = $"{Profile.Guid}-{oNameSlug}-{String.Join("-", oSearchGuids)}"
        Dim oParams = New DocumentResultParams() With {
            .WindowGuid = oWindowGuid
        }

        For Each oSearch In Searches
            oParams.Results.Add(New DocumentResult() With {
                .Title = oSearch.TabCaption,
                .Datatable = oSearch.DataTable
            })
        Next

        Dim oForm As New frmDocumentResultList(_LogConfig, _Environment, oParams)
        AddHandler oForm.FormClosed, AddressOf ProfileResultForm_Closed
        OpenForms.Add(oForm)
        oForm.Show()
    End Sub

    Private Sub OpenDataResults(Profile As ProfileData, Searches As List(Of ProfileSearches.Search))
        Dim oNameSlug = Language.Utils.ConvertTextToSlug(Profile.Name)
        Dim oSearchGuids = Searches.Select(Function(s) s.Guid).ToArray
        Dim oWindowGuid = $"{Profile.Guid}-{oNameSlug}-{String.Join("-", oSearchGuids)}"
        Dim oParams = New DataResultParams() With {
            .WindowGuid = oWindowGuid
        }

        For Each oSearch In Searches
            oParams.Results.Add(New DataResult() With {
                .Title = oSearch.TabCaption,
                .Datatable = oSearch.DataTable
            })
        Next

        Dim oForm As New frmDataResultList(_LogConfig, _Environment, oParams)
        AddHandler oForm.FormClosed, AddressOf ProfileResultForm_Closed
        OpenForms.Add(oForm)
        oForm.Show()
    End Sub

    Private Sub ProfileResultForm_Closed(sender As Object, e As FormClosedEventArgs)
        Dim oShouldOpenAgain As Boolean = False
        Dim oThisForm = New List(Of IResultForm) From {sender}

        If TypeOf sender Is frmDataResultList Or TypeOf sender Is frmDocumentResultList Then
            For Each oForm As IResultForm In OpenForms
                ' Determine if frmProfileMatch should be shown
                If oForm.ShouldReturnToPreviousForm Then
                    oShouldOpenAgain = True
                End If
            Next
        End If

        ' If frmProfileMatch should be shown, close all windows of this profile
        If oShouldOpenAgain Then
            For Each oForm As Form In OpenForms.Except(oThisForm)
                ' Remove the Handler to prevent a loop
                RemoveHandler oForm.FormClosed, AddressOf ProfileResultForm_Closed
                oForm.Close()
            Next

            Show()
        End If
    End Sub
End Class
