Imports System.ComponentModel
Imports System.Drawing
Imports System.IO
Imports System.Windows.Forms
Imports DevExpress.Utils
Imports DevExpress.XtraEditors
Imports DevExpress.XtraGrid
Imports DevExpress.XtraGrid.Columns
Imports DevExpress.XtraGrid.Views.BandedGrid
Imports DevExpress.XtraGrid.Views.Base
Imports DevExpress.XtraGrid.Views.Grid
Imports DevExpress.XtraGrid.Views.Grid.ViewInfo
Imports DevExpress.XtraPrinting
Imports DigitalData.Modules.Config
Imports DigitalData.Modules.EDMI.API
Imports DigitalData.Modules.EDMI.API.Client
Imports DigitalData.Modules.Language
Imports DigitalData.Modules.Logging
Imports DigitalData.Modules.ZooFlow

Public Class frmDocumentResultList
    Implements IResultForm

    ' These are NOT constants, only defaults
    ' Can be changed when calling frmDocumentResultList
    Private COLUMN_FILEPATH As String = "FULL_FILENAME"
    Private COLUMN_FILENAME As String = "Filename"
    Private COLUMN_DOCID As String = "DocID"
    Private COLUMN_ICON As String = "ICON"

    Private Const FILE_OPEN_TIMER_INTERVAL As Integer = 500

    ' Helper Classes
    Private _IDBClient As Client
    Private _LogConfig As LogConfig
    Private _Logger As Logger
    Private _Config As ConfigManager(Of DocumentResultConfig)
    Private _Environment As Environment
    Private _Params As DocumentResultParams
    Private _ResultLists As List(Of DocumentResult)
    Private _Helpers As DocumentResultList
    Private _Filesystem As DigitalData.Modules.Filesystem.File
    Private _GridBuilder As GridBuilder

    ' Runtime variables
    Private _IsLoading As Boolean = True
    Private _ActiveGrid As GridControl = Nothing
    Private _ActiveGridBand As GridBand = Nothing

    ' TODO: Hashes for checking if the opened file was modified externally
    'Private _HashOriginalFile As String = Nothing
    'Private _HashOpenedFile As String = Nothing

    Private WithEvents _FileOpenTimer As New Timer
    Private _OpenDocuments As New DocumentResultCache(50000000)
    Private _CurrentDocument As DocumentResultInfo = Nothing

    Private Property OperationMode As IResultForm.Mode Implements IResultForm.OperationMode

    Public Property ShouldReturnToPreviousForm As Boolean = False Implements IResultForm.ShouldReturnToPreviousForm

    Public Sub New(LogConfig As LogConfig, Environment As Environment, Params As DocumentResultParams)
        ' 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", Params.WindowGuid)

        COLUMN_DOCID = Params.ColumnNames.ObjectIdColumn
        COLUMN_FILENAME = Params.ColumnNames.FilenameColumn
        COLUMN_FILEPATH = Params.ColumnNames.FullPathColumn

        _LogConfig = LogConfig
        _Logger = LogConfig.GetLogger()
        _Config = New ConfigManager(Of DocumentResultConfig)(LogConfig, oConfigPath, oConfigPath)
        _Helpers = New DocumentResultList(LogConfig)
        _Filesystem = New Modules.Filesystem.File(_LogConfig)
        _GridBuilder = New GridBuilder(New List(Of GridView) From {GridView1, GridView2, GridView3})

        _Environment = Environment
        _Params = Params
        _ResultLists = Params.Results

        '_FileOpenTimer.Interval = FILE_OPEN_TIMER_INTERVAL
        '_FileOpenTimer.Start()
    End Sub

    Private Sub frmDocumentResultList_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Try
            If _Environment.Service.IsActive AndAlso _Environment.Service.Address <> String.Empty Then
                OperationMode = IResultForm.Mode.WithAppServer
            Else
                OperationMode = IResultForm.Mode.NoAppServer
            End If

            If OperationMode = IResultForm.Mode.WithAppServer Then
                InitAppServer()
            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
                Throw New ApplicationException("GDPicture Licensekey is missing!")
            End If
            DocumentViewer1.Init(_LogConfig, _Environment.Settings.GdPictureKey)

            'Load config
            SplitContainerControl1.SplitterPosition = _Config.Config.SplitContainer1Distance
            SwitchMainContainerHorizontal.Checked = _Config.Config.SplitContainer1Horizontal
            SplitContainerControl2.SplitterPosition = _Config.Config.SplitContainer2Distance
            SwitchDetailContainerHorizontal.Checked = _Config.Config.SplitContainer2Horizontal

            If OperationMode <> IResultForm.Mode.NoAppServer Then
                ' Location and size will be managed by the ZooFlow Search Window
                If Utils.IsVisibleOnAnyScreen(_Config.Config.WindowLocation) Then
                    If Utils.LocationIsVisible(_Config.Config.WindowLocation) Then
                        Location = _Config.Config.WindowLocation
                    End If
                    If Utils.SizeIsVisible(_Config.Config.WindowSize) Then
                        Size = _Config.Config.WindowSize
                    End If
                End If

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

            _GridBuilder.
                WithDefaults().
                WithReadOnlyOptions()

            AddHandler GridView1.FocusedRowChanged, AddressOf GridView_FocusedRowChanged
            AddHandler GridView2.FocusedRowChanged, AddressOf GridView_FocusedRowChanged
            AddHandler GridView3.FocusedRowChanged, AddressOf GridView_FocusedRowChanged

            UpdateTotalResults()
            UpdateGridData()
        Catch ex As Exception
            _Logger.Error(ex)
            MessageBox.Show("Error while loading results:" & vbNewLine & vbNewLine & ex.Message, Text)
        Finally
            _IsLoading = False
        End Try
    End Sub

    Private Sub GridView_FocusedRowChanged(sender As GridView, e As FocusedRowChangedEventArgs)
        _Helpers.SetRowHandle(e)

        Try
            Reset_Errors()
            Cursor = Cursors.WaitCursor

            If e.FocusedRowHandle >= 0 Then
                Dim oRow = sender.GetDataRow(e.FocusedRowHandle)
                Dim oDocumentInfo As DocumentResultInfo = Nothing

                DocumentViewer1.CloseDocument()

                If OperationMode = IResultForm.Mode.NoAppServer Then
                    oDocumentInfo = LoadFile_Legacy(oRow)
                ElseIf OperationMode = IResultForm.Mode.WithAppServer Then
                    oDocumentInfo = LoadFile_IDB(oRow)
                End If

                If IsNothing(oDocumentInfo) Then
                    Show_Warning("File could not be loaded!")
                    Exit Sub
                End If

                If Not File.Exists(oDocumentInfo.FullPath) Then
                    Show_Warning("File does not exist!")
                    ' TODO: Create checksum after closing, compare and take action
                    '_HashOriginalFile = Nothing
                    Exit Sub
                End If

                If oDocumentInfo.Contents IsNot Nothing Then
                    Dim oFileInfo As New FileInfo(oDocumentInfo.FullPath)

                    DocumentViewer1.LoadFile(oFileInfo.Name, New MemoryStream(oDocumentInfo.Contents))
                Else
                    DocumentViewer1.LoadFile(oDocumentInfo.FullPath)
                End If

                If oDocumentInfo.AccessRight = Rights.AccessRight.VIEW_ONLY Then
                    DocumentViewer1.SetViewOnly(True)
                    RibbonPageGroup_Export.Visible = False
                Else
                    DocumentViewer1.SetViewOnly(False)
                    RibbonPageGroup_Export.Visible = True
                End If

                ' TODO: Create checksum after closing, compare and take action
                '_HashOriginalFile = _Filesystem.GetChecksum(oDocumentInfo.FullPath)
            End If
        Catch ex As Exception
            _Logger.Error(ex)
            Show_CriticalError(ex.Message)
        Finally
            Cursor = Cursors.Default
        End Try
    End Sub

    Private Function InitAppServer() As Boolean
        Dim oSplit As List(Of String) = _Environment.Service.Address.Split(":").ToList()
        Dim oAddress As String = oSplit.Item(0)
        Dim oPort As Integer = oSplit.Item(1)

        _IDBClient = New Client(_LogConfig, oAddress, oPort)

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

        Return True
    End Function

    Private Function LoadFile_Legacy(GridRow As DataRow) As DocumentResultInfo
        Try
            Dim oFullPath = GridRow.Item(COLUMN_FILEPATH)
            Dim oDocumentInfo = New DocumentResultInfo() With {
                .AccessRight = Rights.AccessRight.FULL,
                .FullPath = oFullPath
            }

            If File.Exists(oDocumentInfo.FullPath) Then
                oDocumentInfo = LoadFile_AsByteArray(oDocumentInfo)
                _OpenDocuments.Add(oDocumentInfo)
                _CurrentDocument = oDocumentInfo
            End If

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

    Private Function LoadFile_IDB(GridRow As DataRow) As DocumentResultInfo
        Try
            Dim oObjectId = GridRow.Item(COLUMN_DOCID)
            _Logger.Debug($"Getting Information for oObjectId: {oObjectId}")

            ' This needs to be Sync bc otherwise the PopupMenuShowing event will fire before this method loaded the Document Info
            Dim oDocumentInfo As DocumentInfo = _IDBClient.GetDocumentInfo(_Environment.User.UserId, oObjectId)
            Dim oResultDocumentInfo As New DocumentResultInfo() With {
                .AccessRight = oDocumentInfo.AccessRight,
                .FullPath = oDocumentInfo.FullPath
            }

            If File.Exists(oResultDocumentInfo.FullPath) Then
                oResultDocumentInfo = LoadFile_AsByteArray(oResultDocumentInfo)
                _OpenDocuments.Add(oResultDocumentInfo)
                _CurrentDocument = oResultDocumentInfo
            End If

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

    Private Function LoadFile_AsByteArray(DocumentInfo As DocumentResultInfo) As DocumentResultInfo
        Try
            Dim oFullPath As String = DocumentInfo.FullPath
            Dim oPathExists = From oFile In _OpenDocuments
                              Where oFile.FullPath = oFullPath And oFile.Contents IsNot Nothing
                              Select oFile
            Dim oExistsInCache = oPathExists.Count() > 0
            Dim oSizeChanged = False
            Dim oWriteTimeChanged = False

            ' Get Information about the file on the filesystem
            Dim oFileInfo As New FileInfo(oFullPath)

            If oExistsInCache Then
                Dim oCachedItem = oPathExists.First()

                If oCachedItem.Contents Is Nothing Then
                    oSizeChanged = False
                Else
                    oSizeChanged = Not (oFileInfo.Length = oCachedItem.Contents.Length)
                End If

                If oCachedItem.LastWriteTime = Nothing Then
                    oWriteTimeChanged = False
                Else
                    oWriteTimeChanged = Not oFileInfo.LastWriteTime.Equals(oCachedItem.LastWriteTime)
                End If

                If oSizeChanged Or oWriteTimeChanged Then
                    Using oStream = File.OpenRead(DocumentInfo.FullPath)
                        Using oMemoryStream = New MemoryStream()
                            oStream.CopyTo(oMemoryStream)
                            DocumentInfo.Contents = oMemoryStream.ToArray()
                            DocumentInfo.LastWriteTime = oFileInfo.LastWriteTime
                        End Using
                    End Using

                    Return DocumentInfo
                Else
                    Return oCachedItem
                End If

            Else
                Using oStream = File.OpenRead(DocumentInfo.FullPath)
                    Using oMemoryStream = New MemoryStream()
                        oStream.CopyTo(oMemoryStream)
                        DocumentInfo.Contents = oMemoryStream.ToArray()
                        DocumentInfo.LastWriteTime = oFileInfo.LastWriteTime
                    End Using
                End Using

                Return DocumentInfo
            End If

        Catch ex As Exception
            _Logger.Error(ex)
            Return DocumentInfo
        End Try
    End Function

    'Private Function LoadFile_AsByteArray(DocumentInfo As DocumentResultInfo)
    '    Try
    '        Dim oLoadedInfo As DocumentResultInfo = Nothing

    '        Dim oFileContents As Byte()
    '        Dim oFullPath As String = DocumentInfo.FullPath
    '        Dim oPathExists = From oFile In _OpenDocuments
    '                          Where oFile.FullPath = oFullPath And oFile.Contents IsNot Nothing
    '                          Select oFile

    '        If oPathExists.Count > 0 Then
    '            Dim oDocumentInfo = oPathExists.First()
    '            Dim oFileInfo As New FileInfo(DocumentInfo.FullPath)
    '            Dim oSizeChanged = False
    '            Dim oWriteTimeChanged = False

    '            If DocumentInfo.Contents Is Nothing Then
    '                oSizeChanged = False
    '            Else
    '                oSizeChanged = Not oFileInfo.Length.Equals(DocumentInfo.Contents?.Length)
    '            End If

    '            If DocumentInfo.LastWriteTime = Nothing Then
    '                oWriteTimeChanged = False
    '            Else
    '                oWriteTimeChanged = Not oFileInfo.LastWriteTime.Equals(DocumentInfo.LastWriteTime)
    '            End If

    '            If oSizeChanged Or oWriteTimeChanged Then

    '            Else
    '                Using oStream = File.OpenRead(oFullPath)
    '                    Using oMemoryStream = New MemoryStream()
    '                        oStream.CopyTo(oMemoryStream)
    '                        oFileContents = oMemoryStream.ToArray()
    '                    End Using
    '                End Using
    '            End If
    '        End If

    '        DocumentInfo.Contents = oFileContents
    '        DocumentInfo.LastWriteTime = oFileInfo.LastWriteTime

    '        Return DocumentInfo
    '    Catch ex As Exception
    '        _Logger.Error(ex)
    '        Return Nothing
    '    End Try
    'End Function

    Public Function RefreshResults(pResults As IEnumerable(Of BaseResult)) As Boolean Implements IResultForm.RefreshResults
        _IsLoading = True
        Try
            UpdateTotalResults()
            UpdateGridData()

            Return True
        Catch ex As Exception
            _Logger.Error(ex)
            MessageBox.Show("Error while loading results:" & vbNewLine & vbNewLine & ex.Message, Text)
            Return False
        Finally
            _IsLoading = False
        End Try
    End Function

    Private Sub ClearGridData()
        GridControl1.DataSource = Nothing
    End Sub

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

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

        GridControl1.DataSource = Result.Datatable
        GridControl1.ForceInitialize()
    End Sub

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

                    LoadGridData(oResult)
                    CreateDocumentGrid(GridView1, oResult)
                    RestoreLayout(GridView1)
                    UpdateGridHeader(_ResultLists, oIndex, oResult.Datatable.Rows.Count)

                Case 1
                    Dim oResult As DocumentResult = _ResultLists.Item(1)

                    LoadGridData(oResult)
                    CreateDocumentGrid(GridView2, oResult)
                    RestoreLayout(GridView2)
                    UpdateGridHeader(_ResultLists, oIndex, oResult.Datatable.Rows.Count)

                Case 2
                    Dim oResult As DocumentResult = _ResultLists.Item(2)

                    LoadGridData(oResult)
                    CreateDocumentGrid(GridView3, oResult)
                    RestoreLayout(GridView3)
                    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 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 DocumentResult)
        Try
            If IsNothing(GridView.Columns("ICON")) Then
                Dim oIconColumn = GridView.Columns.AddVisible("ICON", "ICON")
                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 oCreated, oChanged As String
            If _Environment?.User?.Language <> "de-DE" Then
                oChanged = "Changed"
                oCreated = "Created"
            Else
                oChanged = "Geändert"
                oCreated = "Erstellt"
            End If

            Try
                Dim oDocIdColumn As GridColumn = GridView.Columns(COLUMN_DOCID)
                If Not IsNothing(oDocIdColumn) Then
                    oDocIdColumn.Visible = False
                End If

                Dim oFilePathColumn As GridColumn = GridView.Columns(COLUMN_FILEPATH)
                If Not IsNothing(oFilePathColumn) Then
                    oFilePathColumn.Visible = False

                    ' Hide Fullpath column completely in AppServer-Mode
                    If OperationMode = IResultForm.Mode.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 = 30
            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 GridView1_CustomDrawCell(sender As Object, e As RowCellCustomDrawEventArgs) Handles GridView1.CustomDrawCell
        Try
            If e.RowHandle < 0 Then
                Exit Sub
            End If

            e.DefaultDraw()

            Dim oView As GridView = TryCast(sender, GridView)
            Dim oCellInfo As GridCellInfo = TryCast(e.Cell, GridCellInfo)
            Dim oRow As DataRow = oView.GetDataRow(e.RowHandle)
            Dim oValue = oRow.Item(COLUMN_FILENAME)

            If e.Column.FieldName = COLUMN_ICON Then
                Dim oIcon = _Helpers.GetIconByExtension(oValue)
                Dim offsetX = 0
                Dim offsetY = 0

                e.Cache.DrawImage(oIcon, e.Bounds.X + offsetX, e.Bounds.Y + offsetY, 18, 18)
            End If
        Catch ex As Exception
            _Logger.Error(ex)
        End Try
    End Sub

    Private Function TryGetItem(DataRow As DataRow, ColumnName As String, Optional DefaultValue As String = "") As String
        Try
            Return DataRow.Item(ColumnName)
        Catch ex As Exception
            Return DefaultValue
        End Try
    End Function

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

        If _Config IsNot Nothing And _IsLoading = False Then
            _Config.Config.SplitContainer1Horizontal = SwitchMainContainerHorizontal.Checked
            _Config.Save()
        End If
    End Sub

    Private Sub SwitchDetailContainerHorizontal2_CheckedChanged(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles SwitchDetailContainerHorizontal.CheckedChanged
        SplitContainerControl2.Horizontal = SwitchDetailContainerHorizontal.Checked

        If _Config IsNot Nothing And _IsLoading = False Then
            _Config.Config.SplitContainer2Horizontal = SwitchDetailContainerHorizontal.Checked
            _Config.Save()
        End If
        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
                MessageBox.Show("Bitte wählen Sie eine Tabelle aus, die Sie exportieren möchten", Text, MessageBoxButtons.OK)
            End If
        End Sub

        Private Sub SplitContainerControl1_SplitterPositionChanged(sender As Object, e As EventArgs) Handles SplitContainerControl1.SplitterPositionChanged
            If _IsLoading = False Then
                _Config.Config.SplitContainer1Distance = SplitContainerControl1.SplitterPosition
                _Config.Save()
            End If
        End Sub

        Private Sub SplitContainerControl2_SplitterPositionChanged(sender As Object, e As EventArgs) Handles SplitContainerControl2.SplitterPositionChanged
            If _IsLoading = False Then
                _Config.Config.SplitContainer2Distance = SplitContainerControl2.SplitterPosition
                _Config.Save()
            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 GetDevexpressGrid_LayoutName(pGridView As GridView)
            Dim Filename As String = $"DevExpressGridViewDocResult_{pGridView.Name}UserLayout.xml"
            Return Path.Combine(_Config.UserConfigPath.Replace("UserConfig.xml", ""), Filename)
        End Function
        Private Function GetActiveGridControl() As GridControl
            If _ActiveGrid Is Nothing Then
                Return Nothing
            End If

            Return _ActiveGrid
        End Function

        Private Sub GridViewSave_Layout(pGridView As GridView)
            Try
                Dim oXml As String = GetDevexpressGrid_LayoutName(pGridView)
                pGridView.SaveLayoutToXml(oXml, OptionsLayoutBase.FullLayout)
            Catch ex As Exception
                _Logger.Error(ex)
                _Logger.Info("Error while saving GridLayout: " & ex.Message)
            End Try
        End Sub
        Private Sub RestoreLayout(pGridView As GridView)
            Try
                Dim oLayoutFile As String = GetDevexpressGrid_LayoutName(pGridView)
                If File.Exists(oLayoutFile) Then
                    pGridView.RestoreLayoutFromXml(oLayoutFile, OptionsLayoutBase.FullLayout)
                End If
            Catch ex As Exception
                _Logger.Error(ex)
                _Logger.Info("Error while restoring layout: " & ex.Message)
            End Try
        End Sub

        Private Sub GridControl_Enter(sender As GridControl, e As EventArgs) Handles GridControl1.Enter, GridControl2.Enter, GridControl3.Enter
            _ActiveGrid = sender
            BarButtonItem5.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 OpenFolderPath()
            Try
                Dim oRow = GetActiveRow()

                If oRow IsNot Nothing Then
                    Dim oFilename = _CurrentDocument.FullPath
                    Dim oDirectory = IO.Path.GetDirectoryName(oFilename)
                    Process.Start(oDirectory)
                End If
            Catch ex As Exception
                _Logger.Error(ex)
            End Try
        End Sub

        Private Sub OpenFile()
            Try
                If _CurrentDocument IsNot Nothing Then
                    Dim oFilename = _CurrentDocument.FullPath
                    DocumentPropertyMenu_FileOpened(Me, oFilename)
                End If
            Catch ex As Exception
                _Logger.Error(ex)
            End Try
        End Sub



        Private Sub CopyFileName()
            Try
                Dim oRow = GetActiveRow()

                If oRow IsNot Nothing Then
                    Dim oFilename = _CurrentDocument.FullPath
                    Clipboard.SetText(oFilename)
                End If
            Catch ex As Exception
                _Logger.Error(ex)
            End Try
        End Sub

        Private Sub OpenProperties()
            Try
                Dim oRow = GetActiveRow()

                If oRow IsNot Nothing Then
                    Dim oObjectId = oRow.Item(COLUMN_DOCID)
                    Dim oPropertyDialog As New frmObjectPropertyDialog(_LogConfig, _Environment, _IDBClient, oObjectId)
                    oPropertyDialog.Show()
                End If
            Catch ex As Exception
                _Logger.Error(ex)
            End Try
        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 Sub frmDocumentResultList_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
            Try
                _Config.Config.WindowLocation = Location
                _Config.Config.WindowSize = Size
                _Config.Save()

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

        Private Sub GridControl_DoubleClick(sender As Object, e As EventArgs) Handles GridControl1.DoubleClick, GridControl2.DoubleClick, GridControl3.DoubleClick
            If _CurrentDocument IsNot Nothing AndAlso _CurrentDocument.AccessRight > Rights.AccessRight.VIEW_ONLY Then
                OpenFile()
            End If
        End Sub

        Private Sub GridView_PopupMenuShowing(sender As Object, e As PopupMenuShowingEventArgs) _
        Handles GridView2.PopupMenuShowing, GridView3.PopupMenuShowing, GridView1.PopupMenuShowing
            Try
                Dim oView As GridView = sender

                If e.MenuType = GridMenuType.Row Then
                    Dim oRowHandle = e.HitInfo.RowHandle
                    Dim oRow As DataRow = oView.GetDataRow(oRowHandle)
                    Dim oFilepath As String = _CurrentDocument.FullPath
                    Dim oObjectId As Long = oRow.Item(COLUMN_DOCID)
                    Dim oMenu As New DocumentPropertyMenu(_LogConfig, _Environment, _IDBClient, oFilepath, oObjectId)

                    e.Menu.Items.Clear()

                    For Each oItem In oMenu.GetMenuItems(OperationMode, _CurrentDocument.AccessRight)
                        e.Menu.Items.Add(oItem)
                    Next

                    AddHandler oMenu.FileOpened, AddressOf DocumentPropertyMenu_FileOpened
                    ' AddHandler oMenu.FileClosed, AddressOf DocumentPropertyMenu_FileClosed
                End If
            Catch ex As Exception
                _Logger.Error(ex)
                MsgBox("Unexpected Error while preparing context menu", MsgBoxStyle.Critical, Text)
            End Try
        End Sub

        Public Sub DocumentPropertyMenu_FileOpened(sender As Object, FilePath As String)
            'DocumentViewer1.CloseDocument()

            Dim oProcess = Process.Start(New ProcessStartInfo With {
            .FileName = FilePath
        })
        End Sub

        Public Sub FileOpenTimer_Elapsed() Handles _FileOpenTimer.Tick
            'Try
            '    Dim oProcesses = Process.GetProcesses()
            '    Dim oIds = (From oProc In oProcesses
            '                Select oProc.Id).
            '                ToList()

            '    Dim oNewFileOpenList As New Dictionary(Of Integer, String)
            '    For Each oOpenFile In _FileOpenList
            '        If oIds.Contains(oOpenFile.Key) Then
            '            oNewFileOpenList.Add(oOpenFile.Key, oOpenFile.Value)
            '        End If
            '    Next

            '    If oNewFileOpenList.Count < _FileOpenList.Count Then
            '        Dim oClosedFiles = _FileOpenList.
            '            Except(oNewFileOpenList).
            '            ToList()

            '        If oClosedFiles.Count = 1 Then
            '            Dim oOpenFile = oClosedFiles.First()
            '            DocumentViewer1.LoadFile(oOpenFile.Value)
            '        Else
            '            ClearGridData()
            '            UpdateGridData()
            '        End If

            '        _FileOpenList = oNewFileOpenList
            '    End If
            'Catch ex As Exception
            '    _Logger.Error(ex)
            'End Try
        End Sub

        Public Sub Show_CriticalError(Message As String)
            labelCriticalError.Visibility = DevExpress.XtraBars.BarItemVisibility.Always
            labelCriticalError.Caption = Message
        End Sub

        Public Sub Show_Warning(Message As String)
            labelWarning.Visibility = DevExpress.XtraBars.BarItemVisibility.Always
            labelWarning.Caption = Message
        End Sub

        Public Sub Reset_Errors()
            labelCriticalError.Visibility = DevExpress.XtraBars.BarItemVisibility.Never
            labelWarning.Visibility = DevExpress.XtraBars.BarItemVisibility.Never
        End Sub

        Private Sub BarButtonItem5_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles BarButtonItem5.ItemClick
            If Not IsNothing(_ActiveGrid) Then
                Try
                    Dim oFile = GetDevexpressGrid_LayoutName(_ActiveGrid.MainView)
                    If File.Exists(oFile) Then
                        File.Delete(oFile)
                    End If
                    UpdateGridData()
                Catch ex As Exception
                    _Logger.Error(ex)
                End Try
            End If
        End Sub

        Private Sub frmDocumentResultList_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
            GridViewSave_Layout(_ActiveGrid.MainView)
        End Sub

        Private _DragBoxFromMouseDown As Rectangle
        Private _ScreenOffset As Point

        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 Class