Imports System.ComponentModel
Imports System.Drawing
Imports System.IO
Imports System.Windows.Forms
Imports DevExpress.Utils
Imports DevExpress.XtraBars
Imports DevExpress.XtraEditors
Imports DevExpress.XtraGrid
Imports DevExpress.XtraGrid.Views.BandedGrid
Imports DevExpress.XtraGrid.Views.Base
Imports DevExpress.XtraGrid.Views.Grid
Imports DevExpress.XtraPrinting
Imports DigitalData.Modules.Config
Imports DigitalData.Modules.EDMI.API
Imports DigitalData.Modules.EDMI.API.EDMIServiceReference
Imports DigitalData.Modules.Language
Imports DigitalData.Modules.Logging
Imports DigitalData.Modules.ZooFlow
Imports DigitalData.Modules.ZooFlow.Constants
Imports DigitalData.Modules.Base.IDB.FileStore
'Imports DigitalData.GUIs.Common.Base
Imports DigitalData.GUIs.Common.DocumentResultList

Public Class frmDocumentResultList
    Implements IResultForm, IBaseForm

    ' Constants
    Private Const FILE_OPEN_TIMER_INTERVAL As Integer = 500
    Private Const SaveWindowLocationAndSize As Integer = 1

    ' Interface implementations
    Private ReadOnly Property LogConfig As LogConfig Implements IBaseForm.LogConfig
    Private ReadOnly Property Logger As Logger Implements IBaseForm.Logger
    Public Property ShouldReturnToPreviousForm As Boolean = False Implements IResultForm.ShouldReturnToPreviousForm

    ' Helper Classes
    Private Client As Client
    Private Documentloader As Loader
    Private ControlManager As AttributeControls
    Private CheckoutManager As CheckInOut

    Private ReadOnly Config As ConfigManager(Of Config)
    Private ReadOnly Environment As Environment
    Private ReadOnly Filesystem As Modules.Filesystem.File
    Private ReadOnly GridBuilder As GridBuilder
    Private ReadOnly FileEx As Modules.Windows.File
    Private ReadOnly Helpers As DocumentResultList.Helpers
    Private ReadOnly Params As Params
    Private ReadOnly LayoutManager As Layout
    Private ReadOnly FormHelper As FormHelper
    Private ReadOnly Workspace As Workspace(Of Config)
    Private WithEvents Watcher As Watcher

    ' Runtime variables
    Private Property ResultLists As List(Of DocumentResult)

    Private IsLoading As Boolean = True
    Private _DragBoxFromMouseDown As Rectangle
    Private _ScreenOffset As Point
    Private _CurrentDocument As DocumentResultList.Document = Nothing
    Private ReadOnly UserLanguage As String

    Private ReadOnly ColumnFilepath As String = "FULL_FILENAME"
    Private ReadOnly ColumnFilename As String = "Filename"
    Private ReadOnly ColumnDocumentId As String = "DocID"
    Private ReadOnly ColumnIcon As String = "ICON"
    Private ReadOnly ColumnCheckedOut As String = "CHECKED_OUT"
    Private ReadOnly FontSizeDeltaList As New List(Of FontSetting) From {
        New FontSetting With {.Title = "Normal", .Value = 0},
        New FontSetting With {.Title = "Groß", .Value = 1},
        New FontSetting With {.Title = "Größer", .Value = 2},
        New FontSetting With {.Title = "Noch Größer", .Value = 3}
    }

    Private Property _ActiveGrid As GridControl = Nothing
    Private Property _ActiveGridBand As GridBand = Nothing
    Private Property GridList As List(Of GridControl)
    Private Property ViewList As List(Of BandedGridView)
    Private Property OperationMode As OperationMode Implements IResultForm.OperationMode

    Public ReadOnly Property Config1 As ConfigManager(Of Config)
        Get
            Return Config
        End Get
    End Property

    Public Event NeedsRefresh As EventHandler(Of Integer) Implements IResultForm.NeedsRefresh
    Public Event ResultsRefreshed As EventHandler(Of List(Of DocumentResultList.DocumentResult))

    Public Event NeedsNewSavedSearch As EventHandler
    Public Event SearchSaved As EventHandler

    Private Delegate Sub DatasourceDelegate(View As GridView, Datasource As Object)
    Private Delegate Function RefreshResultsDelegate(Results As IEnumerable(Of BaseResult)) As Boolean

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

        ' Fügen Sie Initialisierungen nach dem InitializeComponent()-Aufruf hinzu.
        Dim oConfigPath As String = Path.Combine(Application.UserAppDataPath, "ResultList", pParams.WindowGuid)

        ColumnDocumentId = pParams.ColumnNames.ObjectIdColumn
        ColumnFilename = pParams.ColumnNames.FilenameColumn
        ColumnFilepath = pParams.ColumnNames.FullPathColumn
        ColumnIcon = pParams.ColumnNames.IconColumn

        LogConfig = pLogConfig
        Logger = pLogConfig.GetLogger()
        FormHelper = New FormHelper(pLogConfig, Me)

        Environment = pEnvironment
        Params = pParams
        ResultLists = pParams.Results

        Config = New ConfigManager(Of Config)(pLogConfig, oConfigPath, oConfigPath)
        Helpers = New DocumentResultList.Helpers(pLogConfig)
        Filesystem = New Modules.Filesystem.File(pLogConfig)
        GridBuilder = New GridBuilder(New List(Of GridView) From {GridView1, GridView2, GridView3})
        FileEx = New Modules.Windows.File(pLogConfig)
        LayoutManager = New Layout(pLogConfig, Config, New List(Of GridView) From {GridView1, GridView2, GridView3})
        Workspace = New Workspace(Of Config)(pLogConfig, Config, WorkspaceManager1)

        UserLanguage = Utils.NotNull(Environment.User.Language, State.UserState.LANG_EN_US)
    End Sub

    Private Function GetOperationMode() As OperationMode
        Dim oOperationMode As OperationMode

        If Environment.Service.Client.IsOnline AndAlso Environment.Service.Address <> String.Empty Then
            oOperationMode = OperationMode.WithAppServer
        Else
            oOperationMode = OperationMode.NoAppServer
        End If

        If Params.OperationModeOverride <> OperationMode.None Then
            oOperationMode = Params.OperationModeOverride
        End If

        Return oOperationMode
    End Function

    Private Sub frmDocumentResultList_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Try
            ' Operation mode is either guessed from service settings
            ' or explictly set from OperationModeOverride in Params
            OperationMode = GetOperationMode()
            If OperationMode = OperationMode.WithAppServer Or OperationMode = OperationMode.ZooFlow Then
                InitAppServer()

            End If

            Documentloader = New Loader(LogConfig, OperationMode, Client, Environment.User)

            If OperationMode = OperationMode.NoAppServer Then
                Watcher = New Watcher(LogConfig, pEnableWatching:=False)
            Else
                Watcher = New Watcher(LogConfig)
            End If

            If Params.WindowTitle <> "" Then
                Text = $"{Text} - {Params.WindowTitle}"
            End If

            ' Initialize Viewer with GDPicture.NET License
            If Environment.Settings.GdPictureKey <> String.Empty Then
                DocumentViewer1.Init(LogConfig, Environment.Settings.GdPictureKey)
            End If

            ' Hide options relating to a filepath for zooflow
            If OperationMode = OperationMode.ZooFlow Then
                RibbonPageGroupFilesystem.Visible = False
            End If

            cmbGridFontSize.Items.Clear()
            cmbGridFontSize.Items.AddRange(FontSizeDeltaList)
            BarEditItemGridFontSize.EditValue = FontSizeDeltaList.
                Where(Function(delta) delta.Value = Config.Config.GridFontSizeDelta).
                FirstOrDefault()

            If OperationMode = OperationMode.NoAppServer Then
                'RibbonPageCategoryAttribute.Visible = False
                'RibbonPageActions2.Visible = False
                RibbonPageGroupCheckInOut.Visible = False
                RibbonPageGroupWorkflow.Visible = False
                RibbonPageGroupAttribute.Visible = False
            Else
                RibbonPageGroupFilesystem.Visible = False
            End If

            chkGridShowQuickfilter.Checked = LayoutManager.GetFilterRowVisible()
            chkGridShowGrouping.Checked = LayoutManager.GetGroupPanelVisible()
            chkGridShowTitle.Checked = LayoutManager.GetBandTitleVisible()

            ' Hide the complete Navigation Ribbon Group if desired
            RibbonPageGroup_Navigation.Visible = Params.ShowBackNavigation

            If OperationMode = OperationMode.ZooFlow Or OperationMode = OperationMode.WithAppServer Then
                CtrlObjectPropertyDialog.Initialize(LogConfig, Me, Client, Environment)

                SwitchMainContainerHorizontal.Visibility = BarItemVisibility.Never
                SwitchDetailContainerHorizontal.Visibility = BarItemVisibility.Never
            End If

            If OperationMode = OperationMode.NoAppServer Then
                panelContainerStatus.Visibility = Docking.DockVisibility.Hidden
            End If

            UpdateTotalResults()
            LoadGridDataAndLayout()

            ' Initialize Grid Settings
            GridBuilder.WithReadOnlyOptions()

            ' Force initialize, this is needed so that grid settings are loaded correctly from the workspace
            GridControl1.ForceInitialize()
            GridControl2.ForceInitialize()
            GridControl3.ForceInitialize()

            'Load window settings
            LayoutManager.LoadWindowLocationAndSize(Me)


            ' Load the workspaces from file, maybe do this earlier and get the available workspaces through params
            Workspace.LoadWorkspaces()

            ' Add an event when new workspace is loaded
            AddHandler Workspace.WorkspaceLoaded, AddressOf Workspace_WorkspaceLoaded

            ' This loads the available workspaces into the ribbon
            Workspace.GetWorkspaceButtons(RibbonControl, RibbonPageGroupWorkspace)

            ' This loads the default workspace, for now
            Workspace.LoadWorkspace(Config.Config.SelectedWorkspace)


            ' This needs to done be after loading the grid
            ' so we can set the row handle and start loading the (only) file
            If Params.ShowFileList = False Then
                DockPanelFileList.HideImmediately()
                GridView1.FocusedRowHandle = 0
            Else
                DockPanelFileList.Show()
            End If

            ' Hide the refresh button when nobody handles the refresh event
            If NeedsRefreshEvent IsNot Nothing Then
                RibbonPageRefresh.Visible = True
            Else
                RibbonPageRefresh.Visible = False

            End If

            ' Hide the saved search button when nobody handles the saved search event
            If NeedsNewSavedSearchEvent IsNot Nothing Then
                RibbonPageGroupSavedSearch.Visible = True
            Else
                RibbonPageGroupSavedSearch.Visible = False

            End If

        Catch ex As Exception
            FormHelper.ShowErrorMessage(ex, "Error while loading results")

        Finally
            IsLoading = False

        End Try
    End Sub

    Private Sub Workspace_WorkspaceLoaded(sender As Object, e As String)
        lblCurrentWorkspace.Caption = String.Format(lblCurrentWorkspace.Tag, e)
    End Sub

    Private Sub frmDocumentResultList_Closing(sender As Object, e As CancelEventArgs) Handles Me.FormClosing
        Try
            LayoutManager.SaveWindowLocationAndSize(Me)

            Workspace.SaveWorkspaces()
            Config.Config.SelectedWorkspace = Workspace.CurrentWorkspace
            Config.Save()

            DocumentViewer1.Done()
        Catch ex As Exception
            Logger.Error(ex)
        End Try
    End Sub

    Private Async Sub GridView_FocusedRowChanged(sender As GridView, e As FocusedRowChangedEventArgs) Handles GridView1.FocusedRowChanged, GridView2.FocusedRowChanged, GridView3.FocusedRowChanged
        Helpers.SetRowHandle(e)

        Try
            Cursor = Cursors.WaitCursor

            If e.FocusedRowHandle >= 0 Then
                Dim oRow = sender.GetDataRow(Helpers.ActiveRowHandle)
                Dim oObjectId = oRow.ItemEx(Of Long)(ColumnDocumentId, 0)
                Dim oFullPath = oRow.ItemEx(ColumnFilepath, "")
                Dim oDocument As DocumentResultList.Document = Nothing

                ' Load DocumentInfo 
                oDocument = Documentloader.Load(oObjectId, oFullPath)

                If oDocument Is Nothing Then
                    Exit Sub
                End If

                UpdateRibbonActions(oDocument)

                ' Save reference to current document
                _CurrentDocument = oDocument

                ' Load Document in Document Viewer
                Dim oFileName = $"{oObjectId}.{oDocument.Extension}"
                DocumentViewer1.LoadFile(oFileName, New MemoryStream(oDocument.Contents))
                If IsNothing(oDocument) Then
                    DocumentViewer1.CloseDocument()
                    FormHelper.ShowErrorMessage(New IOException("File could not be loaded!"), "GridView_FocusedRowChanged")

                    Exit Sub
                End If

                If OperationMode = OperationMode.ZooFlow Or OperationMode = OperationMode.WithAppServer Then
                    Await CtrlObjectPropertyDialog.LoadObject(oObjectId)

                    Dim oCheckoutState = Await CheckoutManager.GetCheckoutState(oObjectId)
                    If oCheckoutState IsNot Nothing Then
                        txtCheckedOutWho.EditValue = oCheckoutState.CheckedOutWho
                        dateCheckedOutWhen.EditValue = oCheckoutState.CheckedOutWhen
                    Else
                        txtCheckedOutWho.EditValue = Nothing
                        dateCheckedOutWhen.EditValue = Nothing
                    End If
                End If

            Else
                UpdateRibbonActions(Nothing)
            End If
        Catch ex As Exception
            FormHelper.ShowErrorMessage(ex, "GridView_FocusedRowChanged")
        Finally
            Cursor = Cursors.Default
        End Try
    End Sub

    Private Function UpdateRibbonActions(pDocument As DocumentResultList.Document) As Boolean
        Try
            If pDocument Is Nothing Then
                RibbonPageGroupFilesystem.Enabled = False
                RibbonPageGroupDocument.Enabled = False
                RibbonPageGroupCheckInOut.Enabled = False
                RibbonPageGroupWorkflow.Enabled = False
                RibbonPageGroupAttribute.Enabled = False
                Return True
            Else
                RibbonPageGroupFilesystem.Enabled = True
                RibbonPageGroupDocument.Enabled = True
                RibbonPageGroupCheckInOut.Enabled = True
                RibbonPageGroupWorkflow.Enabled = True
                RibbonPageGroupAttribute.Enabled = True
            End If

            ' Hide Export and filesystem options for view only right
            If pDocument.AccessRight = Rights.AccessRight.VIEW_ONLY Then
                DocumentViewer1.SetViewOnly(True)
                RibbonPageGroupExport.Visible = False

                If OperationMode = OperationMode.NoAppServer Then
                    RibbonPageGroupFilesystem.Visible = False
                    MenuItemProperties.Visibility = BarItemVisibility.Never
                End If
            Else
                DocumentViewer1.SetViewOnly(False)
                RibbonPageGroupExport.Visible = True

                If OperationMode = OperationMode.NoAppServer Then
                    RibbonPageGroupFilesystem.Visible = True
                    MenuItemProperties.Visibility = BarItemVisibility.Always
                End If
            End If

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

#Region "Watcher"

    Public Async Sub Watcher_FileOpened(sender As Object, e As DocumentResultList.Watcher.FileOpenedArgs) Handles Watcher.FileOpened
        Await Client.SetObjectStateAsync(e.File.Document.Id, OBJECT_STATE_FILE_OPENED, New Options.SetObjectStateOptions With {
            .Language = Environment.User.Language,
            .Username = Environment.User.UserName
        })
    End Sub

    Public Async Sub Watcher_FileChanged(sender As Object, e As DocumentResultList.Watcher.FileChangedArgs) Handles Watcher.FileChanged
        Try
            Dim oDoctype As GlobalStateDoctype = Nothing

            If e.File.Document.DocumentType IsNot Nothing Then
                oDoctype = Client.ClientConfig.DocumentTypes.
                    Where(Function(doctype) doctype.Name = e.File.Document.DocumentType).
                    FirstOrDefault()
            End If

            If oDoctype IsNot Nothing Then
                Select Case oDoctype.FileChangedAction
                    Case FILE_CHANGED_OVERWRITE
                        Await Watcher_OverwriteFile(e.File)

                    Case FILE_CHANGED_VERSION
                        Await Watcher_VersionFile(e.File)

                    Case FILE_CHANGED_QUESTION
                        Await Watcher_Ask(e.File)

                    Case Else
                        Await Watcher_Ask(e.File)

                End Select

            Else
                Await Watcher_Ask(e.File)

            End If

        Catch ex As Exception
            FormHelper.ShowErrorMessage(ex, "Watcher_FileChanged")

        Finally
            ' Signal to the watcher that the file is no longer in use
            Watcher.FileSaved(e.File)

        End Try
    End Sub

    Private Async Function Watcher_OverwriteFile(pFile As DocumentResultList.Watcher.OpenFile) As Task
        Await Watcher_UpdateFile(pFile, pCreateNewVersion:=False)
    End Function

    Private Async Function Watcher_VersionFile(pFile As DocumentResultList.Watcher.OpenFile) As Task
        Await Watcher_UpdateFile(pFile, pCreateNewVersion:=True)
    End Function

    Private Async Function Watcher_UpdateFile(pFile As DocumentResultList.Watcher.OpenFile, pCreateNewVersion As Boolean) As Task
        Dim oFileInfo As New FileInfo(pFile.FilePath)
        Dim oDisplayName As String = pFile.Document.DisplayFileName
        Dim oObjectId = Await Client.UpdateFileAsync(pFile.Document.Id, pFile.FilePath, New Options.UpdateFileOptions With {
            .CreateNewFileVersion = pCreateNewVersion,
            .Language = Environment.User.Language,
            .Username = Environment.User.UserName
        })
        Documentloader.Invalidate(pFile.Document)

        If IsNothing(oObjectId) Then
            MsgBox($"Beim Speichern der Datei '{oDisplayName}' Fehler ist ein Fehler aufgetreten!", MsgBoxStyle.Critical, Text)
        Else
            'MsgBox($"Die Datei '{oDisplayName}' wurde erfolgreich gespeichert!", MsgBoxStyle.Information, Text)
            RaiseEvent NeedsRefresh(Me, Params.ProfileGuid)
        End If
    End Function

    Private Async Function Watcher_Ask(pFile As DocumentResultList.Watcher.OpenFile) As Task
        Dim oFileInfo = New FileInfo(pFile.FilePath)
        Dim oDisplayName = pFile.Document.DisplayFileName
        Dim oMessage = $"Die Datei '{oDisplayName}' wurde außerhalb des Systems verändert. Wollen Sie diese Änderung als neue Version in das System übernehmen oder überschreiben?"

        Dim oMessageBox As New NNMsgBoxEx(oMessage, "Datei verändert", MessageBoxIcon.Question)
        oMessageBox.SetButtons("Überschreiben", "Neue Version", "Abbrechen")
        oMessageBox.ShowDialog()

        Select Case oMessageBox.Result
            Case NNMsgBoxEx.DialogBoxResult.Button1
                Await Watcher_OverwriteFile(pFile)

            Case NNMsgBoxEx.DialogBoxResult.Button2
                Await Watcher_VersionFile(pFile)

            Case Else
                ' Cancel, do nothing

        End Select
    End Function
#End Region

    Private Function InitAppServer() As Boolean
        Dim oServerAddress = Client.ParseServiceAddress(Environment.Service.Client.ServerAddress)
        Dim oAddress As String = oServerAddress.Item1
        Dim oPort As Integer = oServerAddress.Item2

        Client = New Client(LogConfig, oAddress, oPort)
        ControlManager = New AttributeControls(LogConfig, Environment, Client)
        CheckoutManager = New CheckInOut(LogConfig, Client)

        If Not Client.Connect() Then
            Logger.Warn("Client could not connect to Service at [{0}]", Environment.Service.Address)
            Return False
        End If

        Return True
    End Function


    Public Function RefreshResults(pResults As IEnumerable(Of BaseResult)) As Boolean Implements IResultForm.RefreshResults
        ' This is needed to update the grid from another form like frmMatch
        ' Another form means another thread, so we need a delegate here
        If InvokeRequired Then
            Dim oDelegate As New RefreshResultsDelegate(AddressOf RefreshResults)
            Return GridControl1.Invoke(oDelegate, pResults)
        Else
            IsLoading = True
            Try
                ' Save current row handle and unset it
                Dim oCurrentRowHandle As Integer = GridView1.FocusedRowHandle
                GridView1.FocusedRowHandle = GridControl.InvalidRowHandle

                ' Save the new results
                ResultLists = pResults

                ' Remove the current document from 
                Documentloader.ClearCache()

                ' Update the grid
                UpdateTotalResults()
                LoadGridDataAndLayout()

                ' After the new results are loaded, set the old row handle
                ' to trigger the row change events and load object properties
                GridView1.FocusedRowHandle = oCurrentRowHandle

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

                MessageBox.Show("Error while refreshing results:" & vbNewLine & vbNewLine & ex.Message, Text, MessageBoxButtons.OK, MessageBoxIcon.Error)
                Return False
            Finally
                IsLoading = False
            End Try
        End If
    End Function

    Private Sub LoadGridData(View As GridView, Result As DocumentResultList.DocumentResult)
        If Result.Datatable.Columns.Contains(ColumnDocumentId) = False Then
            Throw New ApplicationException($"Datatable is missing DocId Column [{ColumnDocumentId}] for search {Result.Title}!")
        End If

        If OperationMode = OperationMode.NoAppServer And Result.Datatable.Columns.Contains(ColumnFilepath) = False Then
            Throw New ApplicationException($"Datatable is missing Filepath Column [{ColumnFilepath}] for search {Result.Title}!")
        End If

        SetGridDataSource(View, Result.Datatable)
    End Sub


    Private Sub SetGridDataSource(pView As GridView, pTable As DataTable)
        Dim oSavedRowHandle As Integer = pView.FocusedRowHandle
        pView.BeginDataUpdate()

        Try
            pView.FocusedRowHandle = GridControl.AutoFilterRowHandle
            pView.GridControl.DataSource = Nothing
            pView.GridControl.DataSource = pTable
            pView.FocusedRowHandle = oSavedRowHandle
        Finally
            pView.EndDataUpdate()
        End Try
    End Sub

    Private Sub LoadGridDataAndLayout()
        ' Load Grids
        For oIndex = 0 To ResultLists.Count - 1
            Select Case oIndex
                Case 0
                    Dim oResult As DocumentResultList.DocumentResult = ResultLists.Item(0)

                    LoadGridData(GridView1, oResult)
                    'LayoutManager.GridView_RestoreLayout(GridView1)
                    CreateDocumentGrid(GridView1, oResult)
                    UpdateGridHeader(ResultLists, oIndex, oResult.Datatable.Rows.Count)

                Case 1
                    Dim oResult As DocumentResultList.DocumentResult = ResultLists.Item(1)

                    LoadGridData(GridView2, oResult)
                    'LayoutManager.GridView_RestoreLayout(GridView2)
                    CreateDocumentGrid(GridView2, oResult)
                    UpdateGridHeader(ResultLists, oIndex, oResult.Datatable.Rows.Count)

                Case 2
                    Dim oResult As DocumentResultList.DocumentResult = ResultLists.Item(2)

                    LoadGridData(GridView3, oResult)
                    'LayoutManager.GridView_RestoreLayout(GridView3)
                    CreateDocumentGrid(GridView3, oResult)
                    UpdateGridHeader(ResultLists, oIndex, oResult.Datatable.Rows.Count)

                Case Else
                    MessageBox.Show(Constants.MESSAGE_TOO_MANY_SEARCHES, Text, MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
                    Exit For
            End Select
        Next

        ' Hide Grids depending on Result count
        Select Case ResultLists.Count
            Case 0

                SplitContainerControl1.SetPanelCollapsed(True)
                SplitContainerControl2.SetPanelCollapsed(True)

                SwitchMainContainerHorizontal.Enabled = False
                SwitchDetailContainerHorizontal.Enabled = False

                MessageBox.Show(Constants.MESSAGE_ERROR_IN_SEARCHES, Text, MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
            Case 1
                SplitContainerControl1.PanelVisibility = DevExpress.XtraEditors.SplitPanelVisibility.Panel1
                SplitContainerControl2.PanelVisibility = DevExpress.XtraEditors.SplitPanelVisibility.Panel1

                SplitContainerControl1.SetPanelCollapsed(True)
                SplitContainerControl2.SetPanelCollapsed(True)

                SwitchMainContainerHorizontal.Enabled = False
                SwitchDetailContainerHorizontal.Enabled = False
            Case 2
                SplitContainerControl1.PanelVisibility = DevExpress.XtraEditors.SplitPanelVisibility.Both
                SplitContainerControl2.PanelVisibility = DevExpress.XtraEditors.SplitPanelVisibility.Panel1

                SplitContainerControl2.SetPanelCollapsed(True)

                SwitchDetailContainerHorizontal.Enabled = False
        End Select
    End Sub

    Private Sub UpdateTotalResults()
        Dim oTotalResults = 0

        For Each oList In ResultLists
            oTotalResults += oList.Datatable.Rows.Count
        Next

        labelResultCount.Caption = String.Format(labelResultCount.Caption, oTotalResults)
    End Sub
    Private Sub UpdateGridHeader(pResultList As List(Of DocumentResultList.DocumentResult), pIndex As Integer, pCount As Integer)
        Select Case pIndex
            Case 0
                Dim oResult = pResultList.Item(0)
                GridBand1.Caption = $"{oResult.Title} ({pCount})"

            Case 1
                Dim oResult = pResultList.Item(1)
                GridBand2.Caption = $"{oResult.Title} ({pCount})"

            Case 2
                Dim oResult = pResultList.Item(2)
                GridBand3.Caption = $"{oResult.Title} ({pCount})"
        End Select
    End Sub

    Private Sub CreateDocumentGrid(GridView As BandedGridView, Result As DocumentResultList.DocumentResult)
        Try
            If GridView.Columns.Item(ColumnIcon) Is Nothing Then
                Dim oIconColumn = GridView.Columns.AddVisible(ColumnIcon, ColumnIcon)
                With oIconColumn
                    .OptionsColumn.AllowSort = False
                    .OptionsColumn.AllowSize = False
                    .OptionsColumn.ShowCaption = False
                    .OptionsColumn.FixedWidth = True
                    .Width = 20
                    .MaxWidth = 20
                    .MinWidth = 20
                End With

                Dim oFirstBand As GridBand = GridView.Bands.First()
                oFirstBand.Columns.Add(oIconColumn)
                oFirstBand.Columns.MoveTo(0, oIconColumn)
            End If

            Dim oColumnsToHide As New List(Of String) From {
                ColumnDocumentId,
                ColumnFilepath,
                ColumnFilename,
                ColumnIcon,
                "ADDED_WHEN", "ADDED_WHO", "CHANGED_WHEN", "CHANGED_WHO",
                "Added when", "Added who", "Changed when", "Changed who"
            }

            For Each oFieldName As String In oColumnsToHide
                Try
                    Dim oColumn = GridView.Columns.
                        Where(Function(column) column.FieldName.ToUpper.Equals(oFieldName.ToUpper)).
                        FirstOrDefault()
                    If oColumn IsNot Nothing Then
                        oColumn.VisibleIndex = -1
                    End If
                Catch ex As Exception
                End Try
            Next

            For Each oColumn As BandedGridColumn In GridView.Columns

                If oColumn.ColumnType.Name = "DateTime" Then
                    oColumn.DisplayFormat.FormatType = FormatType.DateTime
                    oColumn.DisplayFormat.FormatString = "g"
                End If

            Next

            'Dim oCreated, oChanged As String
            'If UserLanguage = State.UserState.LANG_DE_DE Then
            '    oChanged = "Geändert"
            '    oCreated = "Erstellt"
            'Else
            '    oCreated = "Created"
            '    oChanged = "Changed"
            'End If
            'Try
            '    Dim oFilePathColumn As GridColumn = GridView.Columns(ColumnFilepath)
            '    If Not IsNothing(oFilePathColumn) Then
            '        ' Hide Fullpath column completely in AppServer-Mode
            '        If OperationMode = OperationMode.WithAppServer Then
            '            oFilePathColumn.OptionsColumn.ShowInCustomizationForm = False
            '        End If
            '    End If

            '    'Dim oCreatedColumn = GridView.Columns(oCreated)
            '    'If Not IsNothing(oCreatedColumn) Then
            '    '    oCreatedColumn.DisplayFormat.FormatType = FormatType.DateTime
            '    '    oCreatedColumn.DisplayFormat.FormatString = Environment.User.DateFormat & " HH:MM:ss"
            '    'End If

            '    'Dim oChangedColumn = GridView.Columns(oChanged)
            '    'If Not IsNothing(oChangedColumn) Then
            '    '    oChangedColumn.DisplayFormat.FormatType = FormatType.DateTime
            '    '    oChangedColumn.DisplayFormat.FormatString = Environment.User.DateFormat & " HH:MM:ss"
            '    'End If
            'Catch ex As Exception
            '    Logger.Error(ex)
            'End Try

            GridView.OptionsView.BestFitMaxRowCount = 5
            GridView.BestFitColumns()
        Catch ex As ApplicationException
            MsgBox($"Error while loading grid data for search {Result.Title}: {vbNewLine}{vbNewLine}{ex.Message}", MsgBoxStyle.Critical, Text)
            Logger.Error(ex)
        Catch ex As Exception
            Logger.Error(ex)
        End Try
    End Sub

    Private Sub BarButtonItemExportGrid1_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles BarButtonItemExportGrid1.ItemClick
        Dim oActiveGrid = GetActiveGridControl()

        If oActiveGrid IsNot Nothing Then
            Dim oGridBand = _ActiveGridBand

            XtraSaveFileDialog.FileName = Utils.ConvertTextToSlug(oGridBand.Caption) & ".xlsx"
            XtraSaveFileDialog.DefaultExt = ".xlsx"

            If XtraSaveFileDialog.ShowDialog() = Windows.Forms.DialogResult.OK Then
                Dim oOptions As New XlsxExportOptions() With {
            .ExportMode = XlsxExportMode.SingleFile
        }
                oActiveGrid.ExportToXlsx(XtraSaveFileDialog.FileName, oOptions)
            End If

        Else
            If UserLanguage = State.UserState.LANG_DE_DE Then
                MessageBox.Show("Bitte wählen Sie eine Tabelle aus, die Sie exportieren möchten", Text, MessageBoxButtons.OK, MessageBoxIcon.Information)
            Else
                MessageBox.Show("Please select a table that you want to export", Text, MessageBoxButtons.OK, MessageBoxIcon.Information)
            End If
        End If
    End Sub

    Private Function GetActiveRow() As DataRow
        Dim oActiveGrid = GetActiveGridControl()
        Dim oActiveRowhandle = Helpers.ActiveRowHandle

        If oActiveGrid IsNot Nothing And oActiveRowhandle <> Constants.NO_ROW_HANDLE Then
            Dim oView = DirectCast(oActiveGrid.DefaultView, GridView)
            Dim oRow = oView.GetDataRow(oActiveRowhandle)
            Return oRow
        Else
            Return Nothing
        End If
    End Function

    Private Function GetActiveGridControl() As GridControl
        If _ActiveGrid Is Nothing Then
            Return Nothing
        End If

        Return _ActiveGrid
    End Function
    Private Sub GridControl_Enter(sender As GridControl, e As EventArgs) Handles GridControl1.Enter, GridControl2.Enter, GridControl3.Enter
        _ActiveGrid = sender
        BarButtonResetGridLayout.Visibility = DevExpress.XtraBars.BarItemVisibility.Always
        BarButtonItemExportGrid1.Visibility = DevExpress.XtraBars.BarItemVisibility.Always
        SetActiveGridBand()
    End Sub

    Private Sub GridView1_FocusedRowChanged(sender As GridView, e As FocusedRowChangedEventArgs) Handles GridView1.FocusedRowChanged, GridView2.FocusedRowChanged, GridView3.FocusedRowChanged
        Dim oGrid As GridControl = sender.GridControl
        _ActiveGrid = oGrid
    End Sub

    Private Sub SetActiveGridBand()
        If _ActiveGrid.Equals(GridControl1) Then
            _ActiveGridBand = GridBand1
        ElseIf _ActiveGrid.Equals(GridControl2) Then
            _ActiveGridBand = GridBand2
        ElseIf _ActiveGrid.Equals(GridControl3) Then
            _ActiveGridBand = GridBand3
        Else
            _ActiveGridBand = Nothing
        End If
    End Sub

    Private Sub GridView1_ColumnFilterChanged(sender As GridView, e As EventArgs) Handles GridView1.ColumnFilterChanged
        Dim oRowCount = sender.RowCount
        UpdateGridHeader(ResultLists, 0, oRowCount)
    End Sub

    Private Sub GridView2_ColumnFilterChanged(sender As GridView, e As EventArgs) Handles GridView2.ColumnFilterChanged
        Dim oRowCount = sender.RowCount
        UpdateGridHeader(ResultLists, 1, oRowCount)
    End Sub

    Private Sub GridView3_ColumnFilterChanged(sender As GridView, e As EventArgs) Handles GridView3.ColumnFilterChanged
        Dim oRowCount = sender.RowCount
        UpdateGridHeader(ResultLists, 2, oRowCount)
    End Sub

    Private Sub BarButtonItem4_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles BarButtonBack.ItemClick
        ShouldReturnToPreviousForm = True
        Close()
    End Sub

    Private Async Sub GridControl_DoubleClick(sender As Object, e As EventArgs) Handles GridControl1.DoubleClick, GridControl2.DoubleClick, GridControl3.DoubleClick
        Try
            If _CurrentDocument IsNot Nothing AndAlso _CurrentDocument.AccessRight > Rights.AccessRight.VIEW_ONLY Then
                Await Watcher.OpenDocument(_CurrentDocument)
            End If
        Catch ex As Exception
            Logger.Error(ex)
        End Try
    End Sub



    Private Function TestFileExists(pTitle As String) As Boolean
        If _CurrentDocument Is Nothing Then
            Return False
        End If

        If File.Exists(_CurrentDocument.FullPath) = False Then
            MessageBox.Show($"Datei {_CurrentDocument.FullPath} existiert nicht oder wurde verschoben!", pTitle, MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
            Return False
        Else
            Return True
        End If
    End Function

    Private Function TestDirectoryExists(pDirectory As String) As Boolean
        If _CurrentDocument Is Nothing Then
            Return False
        End If

        If Directory.Exists(pDirectory) = False Then
            MessageBox.Show($"Ordner {pDirectory} existiert nicht oder wurde verschoben!", Text, MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
            Return False
        Else
            Return True
        End If
    End Function

#Region "File Actions"
    Private Sub MenuItem_OpenProperties_ItemClick(sender As Object, e As ItemClickEventArgs) Handles MenuItemProperties.ItemClick
        If _CurrentDocument Is Nothing Then
            Exit Sub
        End If

        Select Case OperationMode
            Case OperationMode.NoAppServer
                FileEx.OpenFileProperties(_CurrentDocument.FullPath)

            Case Else
                Dim oPropertyDialog As New frmObjectPropertyDialog(LogConfig, Environment, Client, _CurrentDocument.Id)
                oPropertyDialog.Show()
        End Select
    End Sub

    Private Sub MenuItem_CopyFolderpath_ItemClick(sender As Object, e As ItemClickEventArgs) Handles MenuItemFolderpathCopy.ItemClick
        Dim oFolderPath = Path.GetDirectoryName(_CurrentDocument.FullPath)
        Clipboard.SetText(oFolderPath)
    End Sub

    Private Sub MenuItem_CopyFilepath_ItemClick(sender As Object, e As ItemClickEventArgs) Handles MenuItemFilepathCopy.ItemClick
        If _CurrentDocument IsNot Nothing Then
            Dim oPath = Utils.NotNull(_CurrentDocument.FullPath, "")
            If oPath <> String.Empty Then
                Clipboard.SetText(oPath)
            End If
        End If
    End Sub

    Private Async Sub MenuItem_OpenFile_ItemClick(sender As Object, e As ItemClickEventArgs) Handles MenuItemFileOpen.ItemClick
        Try
            Await Watcher.OpenDocument(_CurrentDocument)
        Catch ex As Exception
            Logger.Error(ex)
        End Try
    End Sub

    Private Sub MenuItem_FolderOpen_ItemClick(sender As Object, e As ItemClickEventArgs) Handles MenuItemFolderOpen.ItemClick
        Dim oFolderPath = Path.GetDirectoryName(_CurrentDocument.FullPath)

        If TestDirectoryExists(oFolderPath) = False Then
            Exit Sub
        End If

        Dim oArgs As String = $"/e, /select, ""{oFolderPath}"""
        Dim oInfo As New ProcessStartInfo() With {
            .Arguments = oArgs,
            .FileName = "explorer"
        }

        Process.Start(oInfo)
    End Sub

    Private Async Sub MenuItemCheckOutFile_ItemClick(sender As Object, e As ItemClickEventArgs) Handles MenuItemCheckOutFile.ItemClick
        Dim oObjectId = _CurrentDocument?.Id
        Dim oResultComment As String = ShowCheckInOutCommentForm()
        If IsNothing(oResultComment) Then
            Exit Sub
        End If

        Await Client.CheckOutFile(oObjectId, oResultComment)

    End Sub

    Private Sub MenuItemCheckInFile_ItemClick(sender As Object, e As ItemClickEventArgs) Handles MenuItemCheckInFile.ItemClick
        Dim oObjectId = _CurrentDocument?.Id
        Client.CheckInFile(oObjectId)
    End Sub

    Private Function ShowCheckInOutCommentForm()
        Dim editor As New MemoEdit()
        Dim args As New XtraInputBoxArgs With {
            .Caption = "Checkout/in Kommentar",
            .Prompt = "Kommentar",
            .DefaultButtonIndex = 0,
            .Editor = editor,
            .DefaultResponse = ""
        }
        args.ContentPadding = args.ButtonPadding

        AddHandler args.Showing, AddressOf Args_Showing

        Dim result = XtraInputBox.Show(args).ToString()
        Return result
    End Function

    Private Sub Args_Showing(ByVal sender As Object, ByVal e As XtraMessageShowingArgs)
        e.Form.Icon = Me.Icon
    End Sub

#End Region
#Region "Drag to Export"

    Private Sub GridView1_MouseDown(sender As GridView, e As MouseEventArgs) Handles GridView1.MouseDown
        If sender.FocusedRowHandle >= 0 Then
            Dim oDragSize As Size = SystemInformation.DragSize

            _DragBoxFromMouseDown = New Rectangle(New Point(e.X - (oDragSize.Width / 2), e.Y - (oDragSize.Height / 2)), oDragSize)

        Else
            _DragBoxFromMouseDown = Rectangle.Empty
        End If
    End Sub

    Private Sub GridView1_MouseUp(sender As GridView, e As MouseEventArgs) Handles GridView1.MouseUp
        _DragBoxFromMouseDown = Rectangle.Empty
    End Sub

    Private Sub GridView1_MouseMove(sender As GridView, e As MouseEventArgs) Handles GridView1.MouseMove
        If e.Button AndAlso e.Button = MouseButtons.Left Then
            If _DragBoxFromMouseDown <> Rectangle.Empty And Not _DragBoxFromMouseDown.Contains(e.X, e.Y) Then

                Dim oHitInfo = sender.CalcHitInfo(e.Location)

                If oHitInfo.InRow Then
                    If _CurrentDocument IsNot Nothing AndAlso _CurrentDocument.AccessRight >= Rights.AccessRight.VIEW_EXPORT Then
                        _ScreenOffset = SystemInformation.WorkingArea.Location

                        Dim oFullPath As String = _CurrentDocument.FullPath
                        Dim oFiles As String() = {oFullPath}
                        Dim oData As New DataObject(DataFormats.FileDrop, oFiles)

                        sender.GridControl.DoDragDrop(oData, DragDropEffects.All)
                    End If
                End If
            End If
        End If
    End Sub
#End Region
#Region "Layout"

    Private Sub BarButtonResetLayout_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles BarButtonResetGridLayout.ItemClick
        Try
            If Workspace.ResetWorkspaces() Then
                FormHelper.ShowSuccessMessage("Die gespeicherten Workspaces wurden gelöscht, beim Nächsten Laden wird die Standard-Ansicht geladen.", Text)
            End If
        Catch ex As Exception
            Logger.Error(ex)
        End Try

    End Sub

    Private Sub SwitchMainContainerHorizontal_CheckedChanged(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles SwitchMainContainerHorizontal.CheckedChanged
        SplitContainerControl1.Horizontal = SwitchMainContainerHorizontal.Checked
    End Sub

    Private Sub SwitchDetailContainerHorizontal2_CheckedChanged(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles SwitchDetailContainerHorizontal.CheckedChanged
        SplitContainerControl2.Horizontal = SwitchDetailContainerHorizontal.Checked
    End Sub
#End Region
    Private Sub ButtonRefresh_ItemClick(sender As Object, e As ItemClickEventArgs) Handles ButtonRefresh.ItemClick
        RaiseEvent NeedsRefresh(Me, Params.ProfileGuid)
    End Sub

    Private Sub chkGridShowGrouping_CheckedChanged(sender As Object, e As ItemClickEventArgs) Handles chkGridShowGrouping.CheckedChanged
        If IsLoading = False Then
            LayoutManager.SetGroupPanelVisible(chkGridShowGrouping.Checked)
        End If
    End Sub

    Private Sub chkGridShowQuickfilter_CheckedChanged(sender As Object, e As ItemClickEventArgs) Handles chkGridShowQuickfilter.CheckedChanged
        If IsLoading = False Then
            LayoutManager.SetFilterRowVisible(chkGridShowQuickfilter.Checked)
        End If
    End Sub

    Private Sub chkGridShowTitle_CheckedChanged(sender As Object, e As ItemClickEventArgs) Handles chkGridShowTitle.CheckedChanged
        If IsLoading = False Then
            LayoutManager.SetBandTitleVisible(chkGridShowTitle.Checked)
        End If
    End Sub

    Private Async Sub MenuItemSaveProperties_ItemClick(sender As Object, e As ItemClickEventArgs) Handles MenuItemSaveProperties.ItemClick
        If Await CtrlObjectPropertyDialog.SaveChanges() Then
            RaiseEvent NeedsRefresh(sender, Params.ProfileGuid)
        End If
    End Sub

    Private Sub BarButtonItem11_ItemClick(sender As Object, e As ItemClickEventArgs) Handles BarButtonItem11.ItemClick
        GridView1.ShowCustomization()
    End Sub

    Private Sub CtrlObjectPropertyDialog_Enter(sender As Object, e As EventArgs) Handles CtrlObjectPropertyDialog.Enter
        RibbonPageGroupAttribute.Enabled = True
    End Sub

    Private Sub CtrlObjectPropertyDialog_Leave(sender As Object, e As EventArgs) Handles CtrlObjectPropertyDialog.Leave
        RibbonPageGroupAttribute.Enabled = True
    End Sub

    Private Sub GridView1_RowStyle(sender As Object, e As RowStyleEventArgs) Handles GridView1.RowStyle
        Dim oGridView As BandedGridView = sender
        Dim oRow As DataRowView = oGridView.GetRow(e.RowHandle)

        If OperationMode = OperationMode.WithAppServer Or OperationMode = OperationMode.ZooFlow Then
            Try
                If oRow IsNot Nothing AndAlso oRow.Row.ItemEx(ColumnCheckedOut, False) = True Then
                    e.Appearance.BackColor = Color.LightSalmon
                End If
            Catch ex As Exception
            End Try
        End If

    End Sub

    Private Sub BarEditItemGridFontSize_EditValueChanged(sender As Object, e As EventArgs) Handles BarEditItemGridFontSize.EditValueChanged
        Config.Config.GridFontSizeDelta = DirectCast(BarEditItemGridFontSize.EditValue, FontSetting).Value
        Config.Save()

        GridBuilder.WithFontSizeDelta(Config.Config.GridFontSizeDelta)
    End Sub

    Private Sub btnSaveWorkspace_ItemClick(sender As Object, e As ItemClickEventArgs) Handles btnSaveWorkspace.ItemClick
        If Workspace.SaveWorkspace(Workspace.CurrentWorkspace, pForce:=True) Then
            FormHelper.ShowInfoMessage($"Der Workspace '{Workspace.CurrentWorkspace}' wurde erfolgreich gespeichert!", Text)
        End If
    End Sub

    Private Sub btnSaveWorkspaceAs_ItemClick(sender As Object, e As ItemClickEventArgs) Handles btnSaveWorkspaceAs.ItemClick
        Dim oWorkspaceName = Nothing

        Dim oArgs As New XtraInputBoxArgs() With {
            .Caption = "Neuer Workspace",
            .Prompt = "Bitte vergeben Sie einen Namen für den neuen Workspace:"
        }
        Dim oNewName = XtraInputBox.Show(oArgs)
        If oNewName IsNot Nothing Then
            oWorkspaceName = oNewName
        End If

        If oWorkspaceName IsNot Nothing AndAlso Workspace.SaveWorkspace(oWorkspaceName, pForce:=True) Then
            FormHelper.ShowInfoMessage($"Der Workspace '{oWorkspaceName}' wurde erfolgreich gespeichert!", Text)
            Workspace.LoadWorkspace(oWorkspaceName)
        End If
    End Sub

    Private Sub btnSaveAsMySearch_ItemClick(sender As Object, e As ItemClickEventArgs) Handles btnSaveAsMySearch.ItemClick
        RaiseEvent NeedsNewSavedSearch(Me, New EventArgs)
    End Sub

    Public Class FontSetting
        Public Property Title As String
        Public Property Value As Integer

        Public Overrides Function ToString() As String
            Return Title
        End Function
    End Class


End Class