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.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.Language
Imports DigitalData.Modules.Logging
Imports DigitalData.Modules.ZooFlow
Imports DigitalData.Modules.ZooFlow.Constants

Public Class frmDocumentResultList
    Implements IResultForm

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

    ' Constants
    Private Const OPEN_FILE As String = "Datei öffnen"
    Private Const OPEN_DIRECTORY As String = "Ordner öffnen"
    Private Const COPY_FILE_PATH As String = "Dateipfad kopieren"
    Private Const COPY_FOLDER_PATH As String = "Ordnerpfad kopieren"
    Private Const OPEN_PROPERTIES As String = "Eigenschaften"

    Private Const FILE_OPEN_TIMER_INTERVAL As Integer = 500

    ' Helper Classes
    Private _IDBClient As Client
    Private ReadOnly LogConfig As LogConfig
    Private ReadOnly Logger As Logger
    Private ReadOnly Config As ConfigManager(Of DocumentResultList.Config)
    Private ReadOnly Environment As Environment
    Private ReadOnly ResultLists As List(Of DocumentResultList.DocumentResult)
    Private ReadOnly Filesystem As Modules.Filesystem.File
    Private ReadOnly GridBuilder As GridBuilder
    Private ReadOnly FileEx As Modules.Windows.File
    Private ReadOnly Cache As New DocumentResultList.Cache(50000000)

    Private ReadOnly Helpers As DocumentResultList.Helpers
    Private ReadOnly Params As DocumentResultList.Params
    Private WithEvents Watcher As DocumentResultList.Watcher

    Private _Documentloader As DocumentResultList.Loader

    ' Runtime variables
    Private _IsLoading As Boolean = True
    Private _ActiveGrid As GridControl = Nothing
    Private _ActiveGridBand As GridBand = Nothing
    Private _DragBoxFromMouseDown As Rectangle
    Private _ScreenOffset As Point
    Private _CurrentDocument As DocumentResultList.Document = Nothing
    Private ReadOnly _FileOpenList As New Dictionary(Of Integer, String)
    Private ReadOnly _Language As String

    Private Property OperationMode As OperationMode Implements IResultForm.OperationMode

    Public Property ShouldReturnToPreviousForm As Boolean = False Implements IResultForm.ShouldReturnToPreviousForm

    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)

        COLUMN_DOCID = pParams.ColumnNames.ObjectIdColumn
        COLUMN_FILENAME = pParams.ColumnNames.FilenameColumn
        COLUMN_FILEPATH = pParams.ColumnNames.FullPathColumn
        COLUMN_ICON = pParams.ColumnNames.IconColumn

        LogConfig = pLogConfig
        Logger = pLogConfig.GetLogger()

        Config = New ConfigManager(Of DocumentResultList.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)
        Watcher = New DocumentResultList.Watcher(pLogConfig)

        Environment = pEnvironment
        Params = pParams
        ResultLists = pParams.Results

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

    Private Function GetOperationMode() As OperationMode
        Dim oOperationMode As OperationMode

        If Environment.Service.IsActive 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 DocumentResultList.Loader(LogConfig, OperationMode, _IDBClient, Environment.User)

            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 <> OperationMode.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 = BarItemVisibility.Never
                SwitchDetailContainerHorizontal.Visibility = 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 frmDocumentResultList_Closing(sender As Object, e As CancelEventArgs) Handles Me.FormClosing
        Try
            GridViewSave_Layout(_ActiveGrid.MainView)

            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 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(Helpers.ActiveRowHandle)
                Dim oObjectId = oRow.ItemEx(Of Long)(COLUMN_DOCID, 0)
                Dim oFullPath = oRow.ItemEx(Of String)(COLUMN_FILEPATH, "")
                Dim oDocumentInfo As DocumentResultList.Document = Nothing

                DocumentViewer1.CloseDocument()

                oDocumentInfo = _Documentloader.Load(oObjectId, oFullPath)

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

                Dim oFileName = $"{oObjectId}.{oDocumentInfo.Extension}"

                DocumentViewer1.LoadFile(oFileName, New MemoryStream(oDocumentInfo.Contents))

                ' Save reference to current
                _CurrentDocument = oDocumentInfo

                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
            End If
        Catch ex As Exception
            Logger.Error(ex)
            Show_CriticalError(ex)
        Finally
            Cursor = Cursors.Default
        End Try
    End Sub

    Public Async Sub Watcher_FileChanged(sender As Object, e As DocumentResultList.Watcher.FileChangedArgs) Handles Watcher.FileChanged
        Try
            Dim oFileInfo = New FileInfo(e.File.FilePath)
            Dim oMessage = $"Die Datei '{oFileInfo.Name}' wurde außerhalb des Systems verändert. Wollen Sie diese Änderung als neue Version in das System übernehmen? 'Nein' überschreibt die ursprüngliche Datei."
            Dim oResult As DialogResult = MsgBox(oMessage, MsgBoxStyle.YesNoCancel Or MsgBoxStyle.Question, "Datei verändert")

            ' Three possibilities:
            ' 
            ' - Yes:    Version file
            ' - No:     Overwrite file
            ' - Cancel: Abort update
            Select Case oResult
                Case DialogResult.Cancel
                    MsgBox("Abbruch!")

                Case Else
                    Dim oCreateNewFileVersion = IIf(oResult = DialogResult.Yes, True, False)
                    Dim oObjectId = Await _IDBClient.UpdateFileAsync(e.File.Document.Id, e.File.FilePath, New Options.UpdateFileOptions With {
                        .CreateNewFileVersion = oCreateNewFileVersion,
                        .Language = Environment.User.Language,
                        .Username = Environment.User.UserName
                    })

                    If IsNothing(oObjectId) Then
                        MsgBox($"Beim Speichern der Datei '{oFileInfo.Name}' Fehler ist ein Fehler aufgetreten!", MsgBoxStyle.Critical, Text)
                    Else
                        MsgBox($"Die Datei '{oFileInfo.Name}' wurde erfolgreich gespeichert!", MsgBoxStyle.Information, Text)
                    End If
            End Select

        Catch ex As Exception
            Logger.Error(ex)
            Show_CriticalError(ex)

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

        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)
        ' TODO: INitialize databasewithfallback
        '_Database

        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


    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 LoadGridData(Result As DocumentResultList.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 = OperationMode.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 DocumentResultList.DocumentResult = ResultLists.Item(0)

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

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

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

                Case 2
                    Dim oResult As DocumentResultList.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 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 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 _Language = State.UserState.LANG_DE_DE Then
                oChanged = "Geändert"
                oCreated = "Erstellt"
            Else
                oCreated = "Created"
                oChanged = "Changed"
            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 = 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 = 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 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 _Language = 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
        BarButtonResetLayout.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
        If _CurrentDocument IsNot Nothing AndAlso _CurrentDocument.AccessRight > Rights.AccessRight.VIEW_ONLY Then
            'Process.Start(New ProcessStartInfo With {
            '    .FileName = _CurrentDocument.FullPath
            '})
            Await Watcher.OpenDocument(_CurrentDocument)
        End If
    End Sub

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

    Public Sub Show_CriticalError(pException As Exception)
        labelCriticalError.Visibility = BarItemVisibility.Always
        labelCriticalError.Caption = pException.Message
    End Sub

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

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

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

    Private Function TestPathExists(pTitle As String) As Boolean
        If IO.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 TestObjectIdExists(pObjectId As Long, pTitle As String) As Boolean
        If pObjectId = 0 Then
            MessageBox.Show($"Objekt {pObjectId} existiert nicht oder wurde verschoben!", pTitle, MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
            Return False
        Else
            Return True
        End If
    End Function




#Region "Context Menu"

    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 oObjectId As Long = oRow.Item(COLUMN_DOCID)
                Dim oPoint As Point = oView.GridControl.PointToScreen(e.HitInfo.HitPoint)
                Dim oRight As Rights.AccessRight = _CurrentDocument.AccessRight

                '_CurrentDocumentId = oObjectId
                _CurrentDocument.Id = oObjectId

                If OperationMode = OperationMode.WithAppServer Then
                    If oRight = Rights.AccessRight.FULL Or oRight = Rights.AccessRight.VIEW_EXPORT Then
                        MenuFullAccess_IDB.ShowPopup(oPoint)
                    Else
                        MenuViewAccess_IDB.ShowPopup(oPoint)
                    End If
                ElseIf OperationMode = OperationMode.ZooFlow Then
                    MenuFullAccess_ZOOFLOW.ShowPopup(oPoint)

                Else
                    MenuFullAccess_EDM.ShowPopup(oPoint)
                End If
            Else
                '_CurrentDocumentId = Nothing
                _CurrentDocument.Id = Nothing
            End If
        Catch ex As Exception
            Logger.Error(ex)
            MsgBox("Unexpected Error while preparing context menu", MsgBoxStyle.Critical, Text)
        End Try
    End Sub

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

    Private Sub MenuItemPropertiesECM_ItemClick(sender As Object, e As ItemClickEventArgs) Handles MenuItemPropertiesECM.ItemClick
        If TestPathExists(OPEN_PROPERTIES) = False Then
            Exit Sub
        End If

        FileEx.OpenFileProperties(_CurrentDocument.FullPath)
    End Sub

    Private Sub MenuItemFilepathCopyIDB_ItemClick(sender As Object, e As ItemClickEventArgs) Handles MenuItemFilepathCopy.ItemClick
        Clipboard.SetText(_CurrentDocument.FullPath)
    End Sub

    Private Sub MenuItemFolderOpen_ItemClick(sender As Object, e As ItemClickEventArgs) Handles MenuItemFolderOpen.ItemClick
        If TestPathExists(OPEN_DIRECTORY) = False Then
            Exit Sub
        End If

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

        Process.Start(oInfo)
    End Sub

    Private Sub MenuItemPropertiesIDB_ItemClick(sender As Object, e As ItemClickEventArgs) Handles MenuItemPropertiesIDB.ItemClick
        If TestObjectIdExists(_CurrentDocument.Id, OPEN_PROPERTIES) = False Then
            Exit Sub
        End If

        Dim oPropertyDialog As New frmObjectPropertyDialog(LogConfig, Environment, _IDBClient, _CurrentDocument.Id)
        oPropertyDialog.Show()
    End Sub

    Private Async Sub MenuItemFileOpen_ItemClick(sender As Object, e As ItemClickEventArgs) Handles MenuItemFileOpen.ItemClick
        If TestPathExists(OPEN_FILE) = False Then
            Exit Sub
        End If

        Try
            Await Watcher.OpenDocument(_CurrentDocument)

            'Process.Start(New ProcessStartInfo With {
            '    .FileName = _CurrentDocument.FullPath
            '})
        Catch ex As Exception
            Logger.Error(ex)
        End Try
    End Sub

    Private Sub MenuItemPropertiesZooFlow_ItemClick(sender As Object, e As ItemClickEventArgs) Handles MenuItemPropertiesZooFlow.ItemClick
        If TestObjectIdExists(_CurrentDocument.Id, OPEN_PROPERTIES) = False Then
            Exit Sub
        End If

        Dim oPropertyDialog As New frmObjectPropertyDialog(LogConfig, Environment, _IDBClient, _CurrentDocument.Id)
        oPropertyDialog.Show()
    End Sub

    Private Sub MenuItemsOpenFileZooFlow_ItemClick(sender As Object, e As ItemClickEventArgs) Handles MenuItemsOpenFileZooFlow.ItemClick
        'TODO: Save file to temp dir and then open
    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 SplitContainerControl1_SplitterPositionChanged(sender As Object, e As EventArgs) Handles SplitContainerControl1.SplitterPositionChanged
        If _IsLoading = False Then
            Config.Config.SplitContainer1Distance = SplitContainerControl1.SplitterPosition
        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
        End If
    End Sub

    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
        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
        End If
    End Sub

    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 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 IO.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





#End Region

End Class