Imports DevExpress.XtraGrid
Imports DevExpress.XtraGrid.Views.Base
Imports DevExpress.XtraGrid.Views.Grid
Imports DigitalData.GUIs.ClientSuite.ClassLayout

Public Class UserControlAssignment
    Private _DragDropManager As ClassDragDrop

    Private _ParentIdColumn As String
    Private _ChildIdColumn As String

    Private _ParentList As DataTable
    Private _ChildList As DataTable
    Private _AssignmentList As DataTable

    Private _ParentRecordId As Integer

    Public Property TextParentList As String
    Public Property TextAssignedToParent As String
    Public Property TextNotAssignedToParent As String

    Public Event ChildRemoved(ParentId As Integer, ChildId As Integer, RelationRecordId As Integer)
    Public Event ChildAdded(ParentId As Integer, ChildId As Integer, RelationRecordId As Integer)

    Private Sub UserControlAssignment_Load(sender As Object, e As EventArgs) Handles Me.Load
        _DragDropManager = New ClassDragDrop()
        _DragDropManager.AddGridView(ViewAssignedToParent)
        _DragDropManager.AddGridView(ViewNotAssignedToParent)

        ' Load text customizations
        labelAssignedToParent.Text = TextAssignedToParent
        labelNotAssignedToParent.Text = TextNotAssignedToParent
        labelParentList.Text = TextParentList

        ' Load grid customizations
        Dim oGridPatcher = New ClassControlPatcher(Of GridControl)(Me)
        oGridPatcher.
            ProcessContainer(AddressOf GridControlDefaults.DefaultGridSettings).
            ProcessContainer(AddressOf GridControlDefaults.ReadOnlyGridSettings).
            ProcessControl(AddressOf GridControlDefaults.CheckboxSelectGridSettings, GridNotAssignedToParent).
            ProcessControl(AddressOf GridControlDefaults.CheckboxSelectGridSettings, GridAssignedToParent)

        ' Load view layouts
        Try
            Dim ViewParentListPath = GetLayoutPath(GroupName.LayoutUserManager, Name, ViewParentList.Name)
            Dim ViewAssignedPath = GetLayoutPath(GroupName.LayoutUserManager, Name, ViewAssignedToParent.Name)
            Dim ViewNotAssignedPath = GetLayoutPath(GroupName.LayoutUserManager, Name, ViewNotAssignedToParent.Name)

            If IO.File.Exists(ViewParentListPath) Then
                ViewParentList.RestoreLayoutFromXml(ViewParentListPath)
            End If
            If IO.File.Exists(ViewAssignedPath) Then
                ViewAssignedToParent.RestoreLayoutFromXml(ViewAssignedPath)
            End If
            If IO.File.Exists(ViewNotAssignedPath) Then
                ViewNotAssignedToParent.RestoreLayoutFromXml(ViewNotAssignedPath)
            End If
        Catch ex As Exception

        End Try
    End Sub

    Private Function MaybeCopyToDataTable(RowCollection As EnumerableRowCollection(Of DataRow)) As DataTable
        If RowCollection.Count > 0 Then
            Return RowCollection.CopyToDataTable()
        Else
            Return New DataTable()
        End If
    End Function

    Public Sub Init(ParentList As DataTable, ChildrenList As DataTable, AssignmentList As DataTable, ParentIdColumn As String, ChildIdColumn As String)
        _ParentList = ParentList
        _ChildList = ChildrenList
        _AssignmentList = AssignmentList

        _ParentIdColumn = ParentIdColumn
        _ChildIdColumn = ChildIdColumn

        ' This will trigger FocusedRowChanged, needs to be last!!
        GridParentList.DataSource = ParentList
    End Sub

    Public Sub UpdateData(ParentList As DataTable, ChildrenList As DataTable, AssignmentList As DataTable)
        _ParentList = ParentList
        _ChildList = ChildrenList
        _AssignmentList = AssignmentList

        Dim oFocusedParentRow = ViewParentList.FocusedRowHandle

        ViewParentList.BeginDataUpdate()
        GridParentList.DataSource = ParentList
        ViewParentList.EndDataUpdate()

        ViewParentList.FocusedRowHandle = oFocusedParentRow
    End Sub

    Private Function GetIdsFromDataRows(Rows As List(Of DataRow)) As List(Of Integer)
        Dim oIds As New List(Of Integer)

        For Each oRow As DataRow In Rows
            oIds.Add(oRow.Item(ClassConstants.ATTRIBUTE_ID_COLUMN))
        Next

        Return oIds
    End Function

    Private Function GetModifiedRows(Grid As GridControl, Data As IDataObject) As List(Of DataRow)
        Dim oTable As DataTable = Grid.DataSource
        Dim oModifiedRows As New List(Of DataRow)
        Dim oPrimaryKeys As New List(Of Integer)

        For Each oRow As DataRow In oTable.Rows
            oPrimaryKeys.Add(oRow.Item(ClassConstants.ATTRIBUTE_ID_COLUMN))
        Next

        If Data.GetDataPresent(GetType(GridView)) Then
            Dim oView As GridView = Data.GetData(GetType(GridView))
            Dim oSelectedRows() As Integer = oView.GetSelectedRows()

            If oSelectedRows.Length = 0 Then
                Return oModifiedRows
            End If

            ' Die ausgewählten Rows auslesen und gridUsersAssigned hinzufügen 
            For Each oRowIndex As Integer In oView.GetSelectedRows()
                Dim oRowView As DataRowView = oView.GetRow(oRowIndex)
                Dim oRow As DataRow = oRowView.Row

                If Not oPrimaryKeys.Contains(oRow.Item(ClassConstants.ATTRIBUTE_ID_COLUMN)) Then
                    oModifiedRows.Add(oRow)
                End If
            Next

        ElseIf Data.GetDataPresent(GetType(DataRow)) Then
            Dim oRow As DataRow = Data.GetData(GetType(DataRow))

            If Not oPrimaryKeys.Contains(oRow.Item(ClassConstants.ATTRIBUTE_ID_COLUMN)) Then
                oModifiedRows.Add(oRow)
            End If
        End If

        Return oModifiedRows
    End Function

    Private Function GetAssignmentRecord(ParentId As Integer, ChildId As Integer)
        Dim oRows = _AssignmentList.Select($"{_ParentIdColumn} = {ParentId} And {_ChildIdColumn} = {ChildId}").ToList()

        If oRows.Count = 0 Then
            Return Nothing
        Else
            Return oRows.First().Item(ClassConstants.ATTRIBUTE_ID_COLUMN)
        End If
    End Function

    Private Sub GridNotAssignedToParent_DragDrop(sender As Object, e As DragEventArgs) Handles GridNotAssignedToParent.DragDrop
        Dim oGrid As GridControl = sender
        Dim oChildIds = GetIdsFromDataRows(GetModifiedRows(oGrid, e.Data))

        For Each oChildId In oChildIds
            Dim oRelationRecordId = GetAssignmentRecord(_ParentRecordId, oChildId)

            RaiseEvent ChildRemoved(_ParentRecordId, oChildId, oRelationRecordId)
        Next
    End Sub

    Private Sub GridAssignedToParent_DragDrop(sender As Object, e As DragEventArgs) Handles GridAssignedToParent.DragDrop
        Dim oGrid As GridControl = sender
        Dim oChildIds = GetIdsFromDataRows(GetModifiedRows(oGrid, e.Data))

        For Each oChildId In oChildIds
            Dim oRelationRecordId = GetAssignmentRecord(_ParentRecordId, oChildId)

            RaiseEvent ChildAdded(_ParentRecordId, oChildId, oRelationRecordId)
        Next
    End Sub

    Private Sub ViewParentList_FocusedRowObjectChanged(sender As Object, e As FocusedRowObjectChangedEventArgs) Handles ViewParentList.FocusedRowObjectChanged
        Dim oRowHandle = e.FocusedRowHandle
        _ParentRecordId = ViewParentList.GetRowCellValue(oRowHandle, ClassConstants.ATTRIBUTE_ID_COLUMN)

        Dim oAssignedChildIds = From oRow In _AssignmentList.AsEnumerable()
                                Where oRow.Item(_ParentIdColumn) = _ParentRecordId
                                Select oRow.Item(_ChildIdColumn)

        If _ChildList Is Nothing Then
            Exit Sub
        End If


        Dim oAssignedChildren As EnumerableRowCollection(Of DataRow) = From oRow In _ChildList.AsEnumerable()
                                                                       Where oAssignedChildIds.Contains(oRow.Item(ClassConstants.ATTRIBUTE_ID_COLUMN))

        Dim oNotAssignedChildren As EnumerableRowCollection(Of DataRow) = From oRow In _ChildList.AsEnumerable()
                                                                          Where Not oAssignedChildIds.Contains(oRow.Item(ClassConstants.ATTRIBUTE_ID_COLUMN)) And oRow.Item(ClassConstants.ATTRIBUTE_ID_COLUMN) <> _ParentRecordId

        GridAssignedToParent.DataSource = MaybeCopyToDataTable(oAssignedChildren)
        GridNotAssignedToParent.DataSource = MaybeCopyToDataTable(oNotAssignedChildren)
    End Sub

    Private Sub View_LayoutChanged(sender As Object, e As EventArgs) Handles ViewNotAssignedToParent.Layout, ViewAssignedToParent.Layout, ViewParentList.Layout
        Dim oView As BaseView = sender
        Dim oLayoutPath = GetLayoutPath(GroupName.LayoutUserManager, Name, oView.Name)
        oView.SaveLayoutToXml(oLayoutPath)
    End Sub
End Class
