Imports XCCLibrary

Public Class GUI
    Dim filesFolder As String = "C:\Users\Anton\Documents\Exjobb"       ' Hämta från settings
    Dim HLCtFolder As String = "C:\Users\Anton\Documents\Exjobb\X2021"  ' Hämta från settings

    Dim containerPanel As Panel

    Dim containerW, containerH, containerMidX, containerMidY As Integer
    Dim gratingMaxL As Decimal = 1000
    Dim gratingMaxW As Decimal = 1000
    Dim drawW As Integer = 1
    Dim drawH As Integer = 1
    Dim drawAspect, gratingAspect As Decimal
    Dim scaleDiff As Decimal = 1

    Public pCon1(3) As Decimal 'pCon(0) = pixel X, pCon(2) = SW X, etc.
    Public pCon2(3) As Decimal
    Public pCon3(3) As Decimal
    Public pCon4(3) As Decimal

    Dim points As New Dictionary(Of String, Decimal())
    Dim pointsFunc As New Dictionary(Of String, Boolean)
    Dim pointsOrder As New List(Of String)

    'Dim PointButtons As New List(Of Button)

    Dim pointCounter As Integer
    Dim angleFunctionActive As Boolean = False
    Dim squareFunctionActive As Boolean = False

    ' --- Start method (main) for GUI ---
    Sub GUI_load() Handles MyBase.Load
        containerPanel = DrawingPanel
        AddHandler containerPanel.Paint, AddressOf DrawingPanel_Paint

        Get_DrawboxParameters()

        Set_ContainerPointsX()
        Set_ContainerPointsY()

        Update_GratingDimensions()

        Create_StartPoints()

        Program.Load_XCC(filesFolder, HLCtFolder)
    End Sub

    ' --- Retrive parameters for the drawing box ---
    Private Sub Get_DrawboxParameters()
        containerW = containerPanel.Size.Width
        containerH = containerPanel.Size.Height

        containerMidX = containerW / 2
        containerMidY = containerH / 2

        drawW = containerW - 60
        drawH = containerH - 60

        drawAspect = drawW / drawH
    End Sub

    ' --- Set containers points X-values ---
    Private Sub Set_ContainerPointsX()
        pCon1(0) = containerMidX - drawW / 2
        pCon2(0) = containerMidX + drawW / 2
        pCon3(0) = containerMidX + drawW / 2
        pCon4(0) = containerMidX - drawW / 2
    End Sub

    ' --- Set containers points Y-values ---
    Private Sub Set_ContainerPointsY()
        pCon1(1) = containerMidY - drawH / 2
        pCon2(1) = containerMidY - drawH / 2
        pCon3(1) = containerMidY + drawH / 2
        pCon4(1) = containerMidY + drawH / 2
    End Sub

    ' --- Updates the outer dimensions of the grating ---
    Private Sub Update_GratingDimensions()
        gratingAspect = gratingMaxW / gratingMaxL

        If gratingAspect > drawAspect Then
            'Change draw height
            scaleDiff = gratingMaxW / drawW

            pCon1(1) = containerMidY - gratingMaxL / (scaleDiff * 2)
            pCon2(1) = containerMidY - gratingMaxL / (scaleDiff * 2)
            pCon3(1) = containerMidY + gratingMaxL / (scaleDiff * 2)
            pCon4(1) = containerMidY + gratingMaxL / (scaleDiff * 2)

            Set_ContainerPointsX()
        Else
            'Change draw width
            scaleDiff = gratingMaxL / drawH

            pCon1(0) = containerMidX - gratingMaxW / (scaleDiff * 2)
            pCon2(0) = containerMidX + gratingMaxW / (scaleDiff * 2)
            pCon3(0) = containerMidX + gratingMaxW / (scaleDiff * 2)
            pCon4(0) = containerMidX - gratingMaxW / (scaleDiff * 2)

            Set_ContainerPointsY()
        End If

        'Redraw grating
        Me.Refresh()

        'SW X-values
        pCon1(2) = (-gratingMaxW / 2) / 1000
        pCon2(2) = (gratingMaxW / 2) / 1000
        pCon3(2) = (gratingMaxW / 2) / 1000
        pCon4(2) = (-gratingMaxW / 2) / 1000

        'SW Y-values
        pCon1(3) = (gratingMaxL / 2) / 1000
        pCon2(3) = (gratingMaxL / 2) / 1000
        pCon3(3) = (-gratingMaxL / 2) / 1000
        pCon4(3) = (-gratingMaxL / 2) / 1000
    End Sub

    ' --- Draw all the lines for the container and grating ---
    Private Sub DrawingPanel_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs)
        ' Draw outer grating (red)
        Dim penCon As Pen = New Pen(Color.DarkRed, 1)
        penCon.DashPattern = {4, 8}
        e.Graphics.DrawLine(penCon, CInt(pCon1(0)), CInt(pCon1(1)), CInt(pCon2(0)), CInt(pCon2(1)))
        e.Graphics.DrawLine(penCon, CInt(pCon2(0)), CInt(pCon2(1)), CInt(pCon3(0)), CInt(pCon3(1)))
        e.Graphics.DrawLine(penCon, CInt(pCon3(0)), CInt(pCon3(1)), CInt(pCon4(0)), CInt(pCon4(1)))
        e.Graphics.DrawLine(penCon, CInt(pCon4(0)), CInt(pCon4(1)), CInt(pCon1(0)), CInt(pCon1(1)))

        ' Draw actual grating (black)
        Dim pen As Pen = New Pen(Color.Black, 1)
        For i = 0 To pointsOrder.Count - 1
            Dim pTemp1() As Decimal
            Dim pTemp2() As Decimal

            pTemp1 = points(pointsOrder(i))
            Try
                pTemp2 = points(pointsOrder(i + 1))
            Catch ex As Exception
                pTemp2 = points(pointsOrder(0))
            End Try

            e.Graphics.DrawLine(pen, CInt(pTemp1(0)), CInt(pTemp1(1)), CInt(pTemp2(0)), CInt(pTemp2(1)))
        Next
    End Sub

    ' --- Sets the start points for the grating ---
    Private Sub Create_StartPoints()
        For i = 1 To 4
            points.Add("p" & i, CallByName(Me, "pCon" & i, vbGet))
            pointsFunc.Add("p" & i, True)
            pointsOrder.Add("p" & i)
        Next
    End Sub

    ' --- Generate a table containing all the points X- and Y-values ---
    Private Function Create_PointTable()
        Dim pointTable As New DataTable
        pointTable.Columns.Add("X", GetType(Decimal))
        pointTable.Columns.Add("Y", GetType(Decimal))

        For i = 0 To pointsOrder.Count - 1
            Dim pTemp() As Decimal
            pTemp = points(pointsOrder(i))

            pointTable.Rows.Add()
            pointTable.Rows(i)("X") = pTemp(2)
            pointTable.Rows(i)("Y") = pTemp(3)
        Next

        Return pointTable
    End Function

    ' --- Check if the key pressed is a number ---
    Private Sub Check_IfNumber(e As KeyPressEventArgs)
        If Asc(e.KeyChar) <> 8 Then
            If Asc(e.KeyChar) < 48 Or Asc(e.KeyChar) > 57 Then
                e.Handled = True
            End If
        End If
    End Sub

    ' --- Creates the table with points data used in SW ---
    Private Function Create_ExportTable() As DataTable
        Dim lSpacing As String = ComboBox_MeshSize.Text.Split("x")(0)
        Dim cSpacing As String = ComboBox_MeshSize.Text.Split("x")(1).Split(" ")(0)

        Dim gratingTable As New DataTable
        gratingTable.Columns.Add("TYPE", GetType(String))
        gratingTable.Columns.Add("SERRATED", GetType(Boolean))
        gratingTable.Columns.Add("WIDTH", GetType(Decimal))
        gratingTable.Columns.Add("LENGTH", GetType(Decimal))
        gratingTable.Columns.Add("LOADBAR_THICKNESS", GetType(Decimal))
        gratingTable.Columns.Add("LOADBAR_HEIGHT", GetType(Decimal))
        gratingTable.Columns.Add("LOADBAR_SPACING", GetType(Decimal))
        gratingTable.Columns.Add("CROSSBAR_SPACING", GetType(Decimal))
        gratingTable.Columns.Add("CROSSBAR_DIAMETER", GetType(Decimal))
        gratingTable.Columns.Add("CROSSBAR_THICKNESS", GetType(Decimal))
        gratingTable.Columns.Add("CROSSBAR_HEIGHT", GetType(Decimal))

        gratingTable.Rows.Add()

        gratingTable.Rows(0)("SERRATED") = False    'Hämta från GUI
        gratingTable.Rows(0)("WIDTH") = CDec(ComboBox_Width.Text)
        gratingTable.Rows(0)("LENGTH") = CDec(ComboBox_Length.Text)
        gratingTable.Rows(0)("LOADBAR_THICKNESS") = CDec(ComboBox_Thickness.Text)
        gratingTable.Rows(0)("LOADBAR_HEIGHT") = CDec(ComboBox_Height.Text)
        gratingTable.Rows(0)("LOADBAR_SPACING") = CDec(lSpacing)
        gratingTable.Rows(0)("CROSSBAR_SPACING") = CDec(cSpacing)

        If ComboBox_TypeChooser.Text = "Pressure Welded" Then
            gratingTable.Rows(0)("TYPE") = "pressure_welded"  ' Här behövs namn på HLCt modellen
            gratingTable.Rows(0)("CROSSBAR_DIAMETER") = 5
            gratingTable.Rows(0)("CROSSBAR_THICKNESS") = 0
            gratingTable.Rows(0)("CROSSBAR_HEIGHT") = 0
        Else
            gratingTable.Rows(0)("TYPE") = "type_a"  ' Här behövs namn på HLCt modellen
            gratingTable.Rows(0)("CROSSBAR_DIAMETER") = 0
            gratingTable.Rows(0)("CROSSBAR_THICKNESS") = 2
            gratingTable.Rows(0)("CROSSBAR_HEIGHT") = 15
        End If

        Return gratingTable
    End Function

    Private Sub Create_TextBox(TextBoxName As String, TextBoxText As String, TextBoxLeft As Integer, TextBoxTop As Integer, TextBoxWidth As Integer)
        Dim textBoxTemp As New TextBox
        textBoxTemp.Name = TextBoxName
        textBoxTemp.Text = TextBoxText
        textBoxTemp.Left = TextBoxLeft
        textBoxTemp.Top = TextBoxTop
        textBoxTemp.Width = TextBoxWidth
        textBoxTemp.Font = New Font("Microsoft Sans Serif", 10)
        Me.Controls.Add(textBoxTemp)
    End Sub

    Private Sub Create_Label(LabelName As String, LabelText As String, LabelLeft As Integer, LabelTop As Integer)
        Dim LabelTemp As New Label
        LabelTemp.Name = LabelName
        LabelTemp.Text = LabelText
        LabelTemp.Left = LabelLeft
        LabelTemp.Top = LabelTop
        LabelTemp.Font = New Font("Microsoft Sans Serif", 10)
        Me.Controls.Add(LabelTemp)
    End Sub



    ' ---------------------------------- GUI interactions ----------------------------------

    ' --- When user changes grating type ---
    Private Sub ComboBox_TypeChooser_TextChanged(sender As Object, e As EventArgs) Handles ComboBox_TypeChooser.TextChanged
        ComboBox_MeshSize.Enabled = True
        ComboBox_MeshSize.Items.Clear()
        Dim gratingType As String = ComboBox_TypeChooser.Text
        If gratingType = "Pressure Welded" Then
            ComboBox_MeshSize.Items.Add("12x100 (B9)")      'Tillfällig
            ComboBox_MeshSize.Items.Add("25x50 (F4)")       'Tillfällig
            ComboBox_MeshSize.Items.Add("34x37 (H3)")       'Tillfällig

            For i = 1 To 5
                ComboBox_MeshSize.Items.Add("hej " & i)     'Hämta från databas
            Next
        Else
            For i = 1 To 5
                ComboBox_MeshSize.Items.Add("Test " & i)    'Hämta från databas
            Next
        End If
    End Sub

    ' --- When user changes mesh size ---
    Private Sub ComboBox_MeshSize_TextChanged(sender As Object, e As EventArgs) Handles ComboBox_MeshSize.TextChanged
        ComboBox_Width.Enabled = True
        ComboBox_Length.Enabled = True
        ComboBox_Thickness.Enabled = True
        ComboBox_Height.Enabled = True
        ' Uppdatera fälten med avseende på mesh size
    End Sub

    ' --- Grating width changed ---
    Private Sub WidthB_TextChanged(sender As Object, e As EventArgs) Handles ComboBox_Width.TextChanged
        If ComboBox_Width.Text <> "" Then
            If CDec(ComboBox_Width.Text) > 0 Then
                gratingMaxW = CDec(ComboBox_Width.Text)
                Update_GratingDimensions()
            End If
        End If
    End Sub

    ' --- Check if width is a number ---
    Private Sub ComboBox_Width_KeyPress(sender As Object, e As KeyPressEventArgs) Handles ComboBox_Width.KeyPress
        Check_IfNumber(e)
    End Sub

    ' --- Grating length changed ---
    Private Sub LengthBox_TextChanged(sender As Object, e As EventArgs) Handles ComboBox_Length.TextChanged
        If ComboBox_Length.Text <> "" Then
            If CDec(ComboBox_Length.Text) > 0 Then
                gratingMaxL = CDec(ComboBox_Length.Text)
                Update_GratingDimensions()
            End If
        End If
    End Sub

    ' --- Check if length is a number ---
    Private Sub ComboBox_Length_KeyPress(sender As Object, e As KeyPressEventArgs) Handles ComboBox_Length.KeyPress
        Check_IfNumber(e)
    End Sub

    ' --- When angle button is pressed ---
    Private Sub AngleButton_Click(sender As Object, e As EventArgs) Handles AngleButton.Click
        Dim buttonX As Integer = Me.Controls("AngleButton").Location.X
        Dim buttonY As Integer = Me.Controls("AngleButton").Location.Y

        Create_TextBox("X_TextBox", "", buttonX + 20, buttonY + 40, 60)
        AddHandler Me.Controls("X_TextBox").TextChanged, AddressOf FunctionText_Changed
        Create_Label("X_Label", "X", buttonX, buttonY + 43)

        Create_TextBox("Y_TextBox", "", buttonX + 130, buttonY + 40, 60)
        AddHandler Me.Controls("Y_TextBox").TextChanged, AddressOf FunctionText_Changed
        Create_Label("Y_Label", "Y", buttonX + 110, buttonY + 43)

        angleFunctionActive = True
    End Sub

    ' --- When square button is pressed ---
    Private Sub Button_Square_Click(sender As Object, e As EventArgs) Handles Button_Square.Click
        Dim buttonX As Integer = Me.Controls("Button_Square").Location.X
        Dim buttonY As Integer = Me.Controls("Button_Square").Location.Y

        Create_TextBox("X_TextBox", "", buttonX + 20, buttonY + 40, 60)
        AddHandler Me.Controls("X_TextBox").TextChanged, AddressOf FunctionText_Changed
        Create_Label("X_Label", "X", buttonX, buttonY + 43)

        Create_TextBox("Y_TextBox", "", buttonX + 130, buttonY + 40, 60)
        AddHandler Me.Controls("Y_TextBox").TextChanged, AddressOf FunctionText_Changed
        Create_Label("Y_Label", "Y", buttonX + 110, buttonY + 43)

        ' Add option for corner or side

        squareFunctionActive = True
    End Sub

    Private Sub FunctionText_Changed(sender As TextBox, e As EventArgs)
        If Not Me.Controls("X_TextBox").Text = "" And Not Me.Controls("Y_TextBox").Text = "" Then
            If containerPanel.Controls.Count = 0 Then
                ' Create Buttons for all clickable points
                For i = 0 To pointsOrder.Count - 1
                    If pointsFunc(pointsOrder(i)) Then
                        Dim pointButton As New Button
                        pointButton.Width = 30
                        pointButton.Height = 30

                        pointButton.Left = points(pointsOrder(i))(0) - pointButton.Width / 2
                        pointButton.Top = points(pointsOrder(i))(1) - pointButton.Height / 2

                        pointButton.Name = pointsOrder(i) & "_Button"
                        pointButton.Text = ""

                        pointButton.BackColor = Color.FromArgb(50, Color.Red)
                        pointButton.FlatStyle = FlatStyle.Flat
                        pointButton.FlatAppearance.BorderSize = 0
                        pointButton.FlatAppearance.MouseOverBackColor = Color.Red
                        pointButton.FlatAppearance.MouseDownBackColor = Color.DarkRed

                        Dim gp As New Drawing.Drawing2D.GraphicsPath
                        gp.AddEllipse(New Rectangle(New Point(0, 0), New Size(30, 30)))
                        pointButton.Region = New Region(gp)

                        containerPanel.Controls.Add(pointButton)

                        AddHandler pointButton.Click, AddressOf PointButton_Click
                    End If
                Next
                pointCounter = pointCounter + 1
            End If
        End If
    End Sub

    ' --- When a function button is pressed ---
    Private Sub PointButton_Click(sender As Button, e As EventArgs)
        'Determine which point is being pressed
        Dim pointPressed As String = sender.Name.Split("_")(0)
        Dim index As Integer = pointsOrder.IndexOf(pointPressed)

        ' Remove point buttons
        For i = 0 To pointsOrder.Count - 1
            If pointsFunc(pointsOrder(i)) Then
                RemoveHandler containerPanel.Controls(pointsOrder(i) & "_Button").Click, AddressOf PointButton_Click
                containerPanel.Controls.RemoveByKey(pointsOrder(i) & "_Button")
            End If
        Next

        'Retrive that points coords
        Dim pXP As Decimal = points(pointPressed)(0)
        Dim pYP As Decimal = points(pointPressed)(1)
        Dim pXSW As Decimal = points(pointPressed)(2)
        Dim pYSW As Decimal = points(pointPressed)(3)

        Dim d1P As Decimal = Me.Controls("X_TextBox").Text / scaleDiff   ' BEHÖVS Cdec??
        Dim d2P As Decimal = Me.Controls("Y_TextBox").Text / scaleDiff
        Dim d1SW As Decimal = Me.Controls("X_TextBox").Text / 1000
        Dim d2SW As Decimal = Me.Controls("Y_TextBox").Text / 1000

        Dim numOfNewPoints As Integer

        If angleFunctionActive Then
            If pXP < containerMidX Then
                If pYP > containerMidY Then
                    'Kvadrant 4
                    points.Add("pA" & pointCounter * 2 - 1, {pXP + d1P, pYP, pXSW + d1SW, pYSW})
                    points.Add("pA" & pointCounter * 2, {pXP, pYP - d2P, pXSW, pYSW + d2SW})
                Else
                    'Kvadrant 1
                    points.Add("pA" & pointCounter * 2 - 1, {pXP, pYP + d2P, pXSW, pYSW - d2SW})
                    points.Add("pA" & pointCounter * 2, {pXP + d1P, pYP, pXSW + d1SW, pYSW})
                End If
            Else
                If pYP > containerMidY Then
                    'Kvadrant 3
                    points.Add("pA" & pointCounter * 2 - 1, {pXP, pYP - d2P, pXSW, pYSW + d2SW})
                    points.Add("pA" & pointCounter * 2, {pXP - d1P, pYP, pXSW - d1SW, pYSW})
                Else
                    'Kvadrant 2
                    points.Add("pA" & pointCounter * 2 - 1, {pXP - d1P, pYP, pXSW - d1SW, pYSW})
                    points.Add("pA" & pointCounter * 2, {pXP, pYP + d2P, pXSW, pYSW - d2SW})
                End If
            End If
            pointsFunc.Add("pA" & pointCounter * 2 - 1, False)
            pointsFunc.Add("pA" & pointCounter * 2, False)

            'Insert two new points 
            pointsOrder.Insert(index + 1, "pA" & pointCounter * 2 - 1)
            pointsOrder.Insert(index + 2, "pA" & pointCounter * 2)

            numOfNewPoints = 2
            angleFunctionActive = False

        Else
            If pXP < containerMidX Then
                If pYP > containerMidY Then
                    'Kvadrant 4
                    points.Add("pS" & pointCounter * 3 - 2, {pXP + d1P, pYP, pXSW + d1SW, pYSW})
                    points.Add("pS" & pointCounter * 3 - 1, {pXP + d1P, pYP - d2P, pXSW + d1SW, pYSW + d2SW})
                    points.Add("pS" & pointCounter * 3, {pXP, pYP - d2P, pXSW, pYSW + d2SW})
                Else
                    'Kvadrant 1
                    points.Add("pS" & pointCounter * 3 - 2, {pXP, pYP + d2P, pXSW, pYSW - d2SW})
                    points.Add("pS" & pointCounter * 3 - 1, {pXP + d1P, pYP + d2P, pXSW + d1SW, pYSW - d2SW})
                    points.Add("pS" & pointCounter * 3, {pXP + d1P, pYP, pXSW + d1SW, pYSW})
                End If
            Else
                If pYP > containerMidY Then
                    'Kvadrant 3
                    points.Add("pS" & pointCounter * 3 - 2, {pXP, pYP - d2P, pXSW, pYSW + d2SW})
                    points.Add("pS" & pointCounter * 3 - 1, {pXP - d1P, pYP - d2P, pXSW - d1SW, pYSW + d2SW})
                    points.Add("pS" & pointCounter * 3, {pXP - d1P, pYP, pXSW - d1SW, pYSW})
                Else
                    'Kvadrant 2
                    points.Add("pS" & pointCounter * 3 - 2, {pXP - d1P, pYP, pXSW - d1SW, pYSW})
                    points.Add("pS" & pointCounter * 3 - 1, {pXP - d1P, pYP + d2P, pXSW - d1SW, pYSW - d2SW})
                    points.Add("pS" & pointCounter * 3, {pXP, pYP + d2P, pXSW, pYSW - d2SW})
                End If
            End If
            pointsFunc.Add("pS" & pointCounter * 3 - 2, True)
            pointsFunc.Add("pS" & pointCounter * 3 - 1, False)
            pointsFunc.Add("pS" & pointCounter * 3, True)

            'Insert new points 
            pointsOrder.Insert(index + 1, "pS" & pointCounter * 3 - 2)
            pointsOrder.Insert(index + 2, "pS" & pointCounter * 3 - 1)
            pointsOrder.Insert(index + 3, "pS" & pointCounter * 3)

            numOfNewPoints = 3

            squareFunctionActive = False

        End If
        pointsOrder.RemoveAt(index)

        'Redraw grating
        Me.Refresh()

        RemoveHandler Me.Controls("X_TextBox").TextChanged, AddressOf FunctionText_Changed
        Me.Controls.RemoveByKey("X_TextBox")

        RemoveHandler Me.Controls("Y_TextBox").TextChanged, AddressOf FunctionText_Changed
        Me.Controls.RemoveByKey("Y_TextBox")

        Me.Controls.RemoveByKey("X_Label")
        Me.Controls.RemoveByKey("Y_Label")
    End Sub

    ' --- Settings button clicked ---
    Private Sub SettingsButton_Click(sender As Object, e As EventArgs) Handles SettingsButton.Click
        Program.Update_KB()
    End Sub

    ' --- When export to SW button is pressed ---
    Private Sub ExportSWButton_Click(sender As Object, e As EventArgs) Handles ExportSWButton.Click
        Dim exportTable As DataTable
        exportTable = Create_ExportTable()


        Program.Build_Grating(exportTable)

        'Test för att SW API
        Dim pointTable As New DataTable
        pointTable = Create_PointTable()

        Program.Export_SW(pointTable)
        Program.Create_Drawing()
    End Sub

End Class