Imports System
Imports System.Collections
Imports DevExpress.XtraGrid
Imports DevExpress.Utils
Imports DevExpress.XtraGrid.Columns
Imports DevExpress.XtraGrid.Views.Grid
Imports DigitalData.Modules.Logging

Public Class RefreshHelper
    '<Serializable>
    'Public Structure RowInfo
    '    Public Id As Object
    '    Public Level As Integer
    'End Structure

    ''' <summary>
    ''' Saves information about the current row, like the level and row handle
    ''' </summary>
    <Serializable>
    Public Class RowInfo
        Public Property Id As Object
        Public Property Level As Integer
        Public Property Handle As Integer
    End Class

    Private Property _View As GridView
    Private Property _KeyFieldName As String
    Private Property _Logger As Logger

    Private Property _VisibleRowIndex As Integer = -1

    Private Property _CurrentFilter As String

    Private ReadOnly Property ExpansionViewInfoList() As New List(Of RowInfo)
    Private ReadOnly Property SelectionViewInfoList() As New List(Of RowInfo)
    Private ReadOnly Property ExpandedMasterRowList() As New List(Of Object)

    Public Sub New(pLogConfig As LogConfig, pView As GridView, pKeyFieldName As String)
        _View = pView
        _KeyFieldName = pKeyFieldName
        _Logger = pLogConfig.GetLogger()
    End Sub

    Public Sub SaveViewInfo()
        Try
            SaveExpandedMasterRows()
            SaveExpansionViewInfo()
            SaveSelectionViewInfo()
            SaveVisibleIndex()
            SaveGridFilter()
        Catch ex As Exception
            _Logger.Error(ex)
        End Try
    End Sub

    Public Sub LoadViewInfo()
        Try
            LoadExpandedMasterRows()
            LoadExpansionViewInfo()
            LoadSelectionViewInfo()
            LoadVisibleIndex()
            LoadGridFilter()
        Catch ex As Exception
            _Logger.Error(ex)
        End Try
    End Sub

    Private Function FindParentRowHandle(pRowInfo As RowInfo, oRowHandle As Integer) As Integer
        Dim oParentRowHandle As Integer = _View.GetParentRowHandle(oRowHandle)

        ' Fixes endless loop when parent row handle is below zero
        If oParentRowHandle < 0 Then
            Return oParentRowHandle
        End If

        Do While _View.GetRowLevel(oParentRowHandle) <> pRowInfo.Level
            oParentRowHandle = _View.GetParentRowHandle(oParentRowHandle)
        Loop

        Return oParentRowHandle
    End Function

    Private Function GetKeyColumn() As GridColumn
        Return _View.Columns(_KeyFieldName)
    End Function

    Private Function GetKeyColumnValue(pRowHandle As Integer) As Object
        Return _View.GetRowCellValue(pRowHandle, GetKeyColumn())
    End Function

    Private Sub ExpandRowByRowInfo(pRowInfo As RowInfo)
        'Dim oDataRowHandle As Integer = _View.LocateByValue(0, GetKeyColumn(), rowInfo.Id)
        Dim oDataRowHandle As Integer = pRowInfo.Handle

        If oDataRowHandle <> GridControl.InvalidRowHandle Then
            Dim parentRowHandle As Integer = FindParentRowHandle(pRowInfo, oDataRowHandle)
            _View.SetRowExpanded(parentRowHandle, True, False)
        End If
    End Sub

    Private Function GetRowHandleToSelect(pRowInfo As RowInfo) As Integer
        'Dim oDataRowHandle As Integer = _View.LocateByValue(0, GetKeyColumn(), rowInfo.Id)
        Dim oDataRowHandle As Integer = pRowInfo.Handle

        If oDataRowHandle <> GridControl.InvalidRowHandle Then
            If _View.GetRowLevel(oDataRowHandle) <> pRowInfo.Level Then
                Return FindParentRowHandle(pRowInfo, oDataRowHandle)
            End If
        End If
        Return oDataRowHandle
    End Function

    Private Sub SelectRowByRowInfo(pRowInfo As RowInfo, pIsFocused As Boolean)
        If pIsFocused Then
            _View.FocusedRowHandle = GetRowHandleToSelect(pRowInfo)
        Else
            _View.SelectRow(GetRowHandleToSelect(pRowInfo))
        End If
    End Sub

    Private Sub SaveSelectionViewInfo()
        SelectionViewInfoList.Clear()

        Dim oSelectionArray() As Integer = _View.GetSelectedRows()
        If oSelectionArray IsNot Nothing Then ' otherwise we have a single focused but not selected row
            Dim oRowInfo As New RowInfo

            For oIndex As Integer = 0 To oSelectionArray.Length - 1
                Dim oDataRowHandle As Integer = oSelectionArray(oIndex)
                oRowInfo.Level = _View.GetRowLevel(oDataRowHandle)
                If oDataRowHandle < 0 Then ' group row
                    oDataRowHandle = _View.GetDataRowHandleByGroupRowHandle(oDataRowHandle)
                End If

                oRowInfo.Id = GetKeyColumnValue(oDataRowHandle)
                oRowInfo.Handle = oDataRowHandle

                SelectionViewInfoList.Add(oRowInfo)
            Next
        Else
            SelectionViewInfoList.Add(New RowInfo With {
                .Id = GetKeyColumnValue(_View.FocusedRowHandle),
                .Level = _View.GetRowLevel(_View.FocusedRowHandle),
                .Handle = _View.FocusedRowHandle
            })
        End If
    End Sub

    Private Sub SaveExpansionViewInfo()
        ' Dont do anything if the current view does not have any grouped columns
        If _View.GroupedColumns.Count = 0 Then
            Return
        End If

        ' Clear the list first
        ExpansionViewInfoList.Clear()

        For oIndex As Integer = -1 To Integer.MinValue + 1 Step -1
            If Not _View.IsValidRowHandle(oIndex) Then
                Exit For
            End If
            If _View.GetRowExpanded(oIndex) Then
                Dim oDataRowHandle As Integer = _View.GetDataRowHandleByGroupRowHandle(oIndex)

                ExpansionViewInfoList.Add(New RowInfo With {
                    .Id = GetKeyColumnValue(oDataRowHandle),
                    .Level = _View.GetRowLevel(oIndex),
                    .Handle = oDataRowHandle
                })
            End If
        Next
    End Sub

    Private Sub SaveExpandedMasterRows()
        If _View.GridControl.Views.Count = 1 Then
            Return
        End If

        ExpandedMasterRowList.Clear()

        For oIndex As Integer = 0 To _View.DataRowCount - 1
            If _View.GetMasterRowExpanded(oIndex) Then
                ExpandedMasterRowList.Add(GetKeyColumnValue(oIndex))
            End If
        Next
    End Sub

    Private Sub SaveGridFilter()
        '_CurrentFilter = _View.ActiveFilterString
    End Sub

    Private Sub LoadGridFilter()
        '_View.ActiveFilterString = _CurrentFilter
    End Sub

    Private Sub SaveVisibleIndex()
        If _View.FocusedRowHandle <> GridControl.InvalidRowHandle AndAlso _View.FocusedRowHandle >= 0 Then
            _VisibleRowIndex = _View.GetVisibleIndex(_View.FocusedRowHandle) - _View.TopRowIndex
        Else
            _VisibleRowIndex = 0
        End If
    End Sub

    Private Sub LoadVisibleIndex()
        Try
            If _View.FocusedRowHandle = GridControl.InvalidRowHandle OrElse _View.FocusedRowHandle < 0 Then
                LOGGER.Debug("No valid focused row handle found. Skipping visible index restoration.")
                Return
            End If

            _View.MakeRowVisible(_View.FocusedRowHandle, True)

            Dim currentVisibleIndex As Integer = _View.GetVisibleIndex(_View.FocusedRowHandle)
            Dim newTopRowIndex As Integer = currentVisibleIndex - _VisibleRowIndex

            ' Verhindere negative oder ungültige TopRowIndex-Werte
            If newTopRowIndex >= 0 AndAlso newTopRowIndex < _View.RowCount Then
                _View.TopRowIndex = newTopRowIndex
            Else
                LOGGER.Debug($"Calculated TopRowIndex {newTopRowIndex} is out of bounds. Skipping setting TopRowIndex.")
            End If

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

    Private Sub LoadSelectionViewInfo()
        _View.BeginSelection()
        Try
            _View.ClearSelection()
            For i As Integer = 0 To SelectionViewInfoList.Count - 1
                SelectRowByRowInfo(DirectCast(SelectionViewInfoList(i), RowInfo), i = SelectionViewInfoList.Count - 1)
            Next i
        Catch ex As Exception
            _Logger.Error(ex)
        Finally
            _View.EndSelection()
        End Try
    End Sub

    Private Sub LoadExpansionViewInfo()
        If _View.GroupedColumns.Count = 0 Then
            Return
        End If

        _View.BeginUpdate()
        Try
            _View.CollapseAllGroups()
            For Each info As RowInfo In ExpansionViewInfoList
                ExpandRowByRowInfo(info)
            Next info
        Catch ex As Exception
            _Logger.Error(ex)
        Finally
            _View.EndUpdate()
        End Try
    End Sub

    Private Sub LoadExpandedMasterRows()
        _View.BeginUpdate()
        Try
            _View.CollapseAllDetails()
            Dim oColumn As GridColumn = GetKeyColumn()
            For oIndex As Integer = 0 To ExpandedMasterRowList.Count - 1
                Dim oRowHandle As Integer = _View.LocateByValue(0, oColumn, ExpandedMasterRowList(oIndex))
                _View.SetMasterRowExpanded(oRowHandle, True)
            Next oIndex
        Catch ex As Exception
            _Logger.Error(ex)
        Finally
            _View.EndUpdate()
        End Try
    End Sub



    Public Class SW
        Public label As String
        Public stopwatch As Stopwatch

        Public Sub New(label As String)
            Me.label = label
            stopwatch = New Stopwatch()
            stopwatch.Start()
        End Sub

        Public Function Done() As Long
            If LOGCONFIG.Debug = False Then
                Return 0
            End If

            stopwatch.Stop()
            Dim ts As TimeSpan = stopwatch.Elapsed

            Dim timespan_ = String.Format("{0:00}:{1:00}.{2:00}", ts.Minutes, ts.Seconds, ts.Milliseconds / 10)
            If ts.Minutes > 0 Then
                timespan_ = String.Format("{0:00}:{1:00}.{2:00}", ts.Minutes, ts.Seconds, ts.Milliseconds / 10)
            ElseIf ts.Seconds > 0 And (ts.Minutes > 0) = False Then
                timespan_ = String.Format("{0:00}.{1:00} seconds", ts.Seconds, ts.Milliseconds / 10)
            ElseIf (ts.Seconds > 0) = False And ts.Milliseconds > 0 Then
                timespan_ = String.Format("{0:00}.{1:00} seconds", ts.Seconds, ts.Milliseconds / 10)
            End If
            If timespan_ <> "00:00.00" Then
                Dim message = String.Format("PerformanceWatch {0} || {1}", timespan_, label)

                If LOGCONFIG.Debug = True Then
                    LOGGER.Debug(message)
                End If

            End If
            Return stopwatch.ElapsedMilliseconds
        End Function


    End Class
End Class

