Imports System
Imports System.IO
Imports System.IO.Ports
Imports System.IO.Ports.SerialPort
Imports System.Text
Imports System.Threading
Imports System.Windows.Forms.VisualStyles
Imports System.Windows.Forms.VisualStyles.VisualStyleElement.ProgressBar
Imports FW_Multi_Downloader.My

Public Class MainForm

    Const CNT_PC As Integer = 10
    Public cmdProcess(CNT_PC) As Process
    Public startInfo(CNT_PC) As ProcessStartInfo
    Public runThread(CNT_PC) As Thread

    Public comboBoxPort(CNT_PC) As ComboBox
    Public buttonPortScan(CNT_PC) As Button
    Public textBoxBinary(CNT_PC) As TextBox
    Public buttonFile(CNT_PC) As Button
    Public textBoxCmdWindow(CNT_PC) As TextBox
    Public textBoxInfo(CNT_PC) As TextBox
    Public buttonDownload(CNT_PC) As Button

    Public baudRate As String
    Public binaryFile As String = ""
    Public downloaderFile As String = ""

    Private Sub MainForm_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        SetGroupBoxProcessControls()
        Initialize()

        Me.Text = "Flash Loader Util " & My.Settings.ProgramVersion
    End Sub

    Private Sub SetGroupBoxProcessControls()
        comboBoxPort(1) = comboBoxPort01
        comboBoxPort(2) = comboBoxPort02
        comboBoxPort(3) = comboBoxPort03
        comboBoxPort(4) = comboBoxPort04
        comboBoxPort(5) = comboBoxPort05
        comboBoxPort(6) = comboBoxPort06
        comboBoxPort(7) = comboBoxPort07
        comboBoxPort(8) = comboBoxPort08
        comboBoxPort(9) = comboBoxPort09
        comboBoxPort(10) = comboBoxPort10

        buttonPortScan(1) = buttonPortScan01
        buttonPortScan(2) = buttonPortScan02
        buttonPortScan(3) = buttonPortScan03
        buttonPortScan(4) = buttonPortScan04
        buttonPortScan(5) = buttonPortScan05
        buttonPortScan(6) = buttonPortScan06
        buttonPortScan(7) = buttonPortScan07
        buttonPortScan(8) = buttonPortScan08
        buttonPortScan(9) = buttonPortScan09
        buttonPortScan(10) = buttonPortScan10

        textBoxBinary(1) = textBoxBinary01
        textBoxBinary(2) = textBoxBinary02
        textBoxBinary(3) = textBoxBinary03
        textBoxBinary(4) = textBoxBinary04
        textBoxBinary(5) = textBoxBinary05
        textBoxBinary(6) = textBoxBinary06
        textBoxBinary(7) = textBoxBinary07
        textBoxBinary(8) = textBoxBinary08
        textBoxBinary(9) = textBoxBinary09
        textBoxBinary(10) = textBoxBinary10

        buttonFile(1) = buttonFile01
        buttonFile(2) = buttonFile02
        buttonFile(3) = buttonFile03
        buttonFile(4) = buttonFile04
        buttonFile(5) = buttonFile05
        buttonFile(6) = buttonFile06
        buttonFile(7) = buttonFile07
        buttonFile(8) = buttonFile08
        buttonFile(9) = buttonFile09
        buttonFile(10) = buttonFile10

        textBoxCmdWindow(1) = textBoxCmdWindow01
        textBoxCmdWindow(2) = textBoxCmdWindow02
        textBoxCmdWindow(3) = textBoxCmdWindow03
        textBoxCmdWindow(4) = textBoxCmdWindow04
        textBoxCmdWindow(5) = textBoxCmdWindow05
        textBoxCmdWindow(6) = textBoxCmdWindow06
        textBoxCmdWindow(7) = textBoxCmdWindow07
        textBoxCmdWindow(8) = textBoxCmdWindow08
        textBoxCmdWindow(9) = textBoxCmdWindow09
        textBoxCmdWindow(10) = textBoxCmdWindow10

        textBoxInfo(1) = textBoxInfo01
        textBoxInfo(2) = textBoxInfo02
        textBoxInfo(3) = textBoxInfo03
        textBoxInfo(4) = textBoxInfo04
        textBoxInfo(5) = textBoxInfo05
        textBoxInfo(6) = textBoxInfo06
        textBoxInfo(7) = textBoxInfo07
        textBoxInfo(8) = textBoxInfo08
        textBoxInfo(9) = textBoxInfo09
        textBoxInfo(10) = textBoxInfo10

        buttonDownload(1) = buttonDownload01
        buttonDownload(2) = buttonDownload02
        buttonDownload(3) = buttonDownload03
        buttonDownload(4) = buttonDownload04
        buttonDownload(5) = buttonDownload05
        buttonDownload(6) = buttonDownload06
        buttonDownload(7) = buttonDownload07
        buttonDownload(8) = buttonDownload08
        buttonDownload(9) = buttonDownload09
        buttonDownload(10) = buttonDownload10

    End Sub

    Private Sub Initialize()
        SetDefaultSetting()
        ClearComponent()
        HandleButton()
    End Sub

    Private Sub SetDefaultSetting()
        Dim baudRate() As String = My.Settings.BaudRate.Split("|")
        comboBoxBaudRate.Items.AddRange(baudRate)
        comboBoxBaudRate.SelectedIndex = 0

        LoadComportName(0)

        If My.Settings.BinaryFile.Length <> 0 And File.Exists(My.Settings.BinaryFile) Then
            binaryFile = My.Settings.BinaryFile
            textBoxBinaryDefault.Text = binaryFile
        End If

        If My.Settings.DownloaderFile.Length <> 0 And File.Exists(My.Settings.DownloaderFile) Then
            downloaderFile = My.Settings.DownloaderFile
            textDownloader.Text = downloaderFile
        End If

    End Sub

    Private Sub ClearComponent()
        For i = 1 To CNT_PC
            ClearTextBoxCmdWindow(i)
            ClearTextBoxInfo(i)
        Next
    End Sub

    Private Sub HandleButton()
        For i = 1 To CNT_PC
            HandleButton(i)
        Next
    End Sub

    Private Sub HandleButton(i As Int16)
        buttonDownload(i).Enabled = False

        If comboBoxPort(i).SelectedIndex > -1 And downloaderFile.Length <> 0 And comboBoxBaudRate.SelectedIndex > -1 And binaryFile.Length <> 0 Then
            If textBoxInfo(i).Text = "READY" Or textBoxInfo(i).Text = "FINISHED" Then
                buttonDownload(i).Enabled = True
            End If
        End If
    End Sub

    Private Sub LoadComportName(i As Int16)
        Try
            Dim portName() As String = SerialPort.GetPortNames

            If i = 0 Then
                For j = 1 To CNT_PC
                    comboBoxPort(j).Items.Clear()
                    comboBoxPort(j).Items.AddRange(portName)
                    comboBoxPort(j).Text = "PRESS!"
                Next
            Else
                comboBoxPort(i).Items.Clear()
                comboBoxPort(i).Items.AddRange(portName)
                comboBoxPort(i).Text = "PRESS!"
            End If
        Catch ex As Exception
            MsgBox("COM 포트 에러" & vbCrLf & "", vbOK + vbCritical, Me.Text)
        End Try
    End Sub

    Private Function Openfile(title As String, fileName As String, filter As String) As String
        Dim ofd As OpenFileDialog = New OpenFileDialog
        ofd.Title = title
        ofd.Filter = filter
        If fileName.Length <> 0 Then
            ofd.InitialDirectory = Path.GetDirectoryName(fileName)
        Else
            ofd.InitialDirectory = ""
        End If

        Dim dr As DialogResult = ofd.ShowDialog
        If dr = DialogResult.OK Then
            Return ofd.FileName
        End If

        Return "fail"
    End Function

    Private Sub ButtonFileDefault_Click(sender As Object, e As EventArgs) Handles buttonFileDefault.Click
        Dim fileAddress As String = Openfile("바이너리 파일 불러오기", binaryFile, "바이너리 파일(*.bin;*.hex) | *.bin;*.hex")

        If fileAddress <> "fail" Then
            textBoxBinaryDefault.Text = fileAddress
            binaryFile = fileAddress
            My.Settings.BinaryFile = binaryFile
            My.Settings.Save()
        End If

        HandleButton()
    End Sub

    Private Sub TextBoxBinaryDefault_TextChanged(sender As Object, e As EventArgs) Handles textBoxBinaryDefault.TextChanged
        If textBoxBinaryDefault.Text.Length > 0 Then
            For i = 1 To CNT_PC
                textBoxBinary(i).Text = textBoxBinaryDefault.Text
            Next
        End If

        HandleButton()
    End Sub

    Private Sub buttonDownloader_Click(sender As Object, e As EventArgs) Handles buttonDownloader.Click
        Dim fileAddress As String = Openfile("다운로드 파일 불러오기", downloaderFile, "다운로드 파일(*.exe) | *.exe")

        If fileAddress <> "fail" Then
            textDownloader.Text = fileAddress
            downloaderFile = fileAddress
            My.Settings.DownloaderFile = downloaderFile
            My.Settings.Save()
        End If

        HandleButton()
    End Sub

    Private Sub ButtonDownloadAll_Click(sender As Object, e As EventArgs) Handles buttonDownloadAll.Click
        For i = 1 To CNT_PC
            Dim processNumber As Int16 = i
            If buttonDownload(processNumber).Enabled = True Then
                runThread(processNumber) = New Thread(Sub() RunDownload(processNumber))
                runThread(processNumber).Start()
            End If
        Next
    End Sub

    Private Sub ButtonPortScan_Click(sender As Object, e As EventArgs) _
        Handles buttonPortScan01.Click,
                buttonPortScan02.Click,
                buttonPortScan03.Click,
                buttonPortScan04.Click,
                buttonPortScan05.Click,
                buttonPortScan06.Click,
                buttonPortScan07.Click,
                buttonPortScan08.Click,
                buttonPortScan09.Click,
                buttonPortScan10.Click

        Dim clickedButton As Button = TryCast(sender, Button)
        Dim processNumber As Short = clickedButton.Parent.TabIndex

        LoadComportName(processNumber)
    End Sub

    Private Sub ComboBoxPort_SelectedIndexChanged(sender As Object, e As EventArgs) _
        Handles comboBoxPort01.SelectedIndexChanged,
                comboBoxPort02.SelectedIndexChanged,
                comboBoxPort03.SelectedIndexChanged,
                comboBoxPort04.SelectedIndexChanged,
                comboBoxPort05.SelectedIndexChanged,
                comboBoxPort06.SelectedIndexChanged,
                comboBoxPort07.SelectedIndexChanged,
                comboBoxPort08.SelectedIndexChanged,
                comboBoxPort09.SelectedIndexChanged,
                comboBoxPort10.SelectedIndexChanged

        Dim clickedComboBox As ComboBox = TryCast(sender, ComboBox)
        Dim processNumber As Short = clickedComboBox.Parent.TabIndex

        For i = 1 To CNT_PC
            If comboBoxPort(i).Text <> "PRESS!" And comboBoxPort(i).Text = clickedComboBox.Text And i <> processNumber Then
                MsgBox("Process" & i & "에 선택된 Port Name 입니다." & vbCrLf & "Port Name 을 다시 선택하세요.", vbCritical, Me.Text)
                clickedComboBox.SelectedIndex = -1
                clickedComboBox.Text = "PRESS!"
                Return
            End If
        Next

        HandleButton()
    End Sub

    Private Sub ButtonFile_Click(sender As Object, e As EventArgs) _
        Handles buttonFile01.Click,
                buttonFile02.Click,
                buttonFile03.Click,
                buttonFile04.Click,
                buttonFile05.Click,
                buttonFile06.Click,
                buttonFile07.Click,
                buttonFile08.Click,
                buttonFile09.Click,
                buttonFile10.Click

        Dim fileAddress As String = Openfile("바이너리 파일 불러오기", "", "바이너리 파일(*.bin;*.hex) | *.bin;*.hex")

        If fileAddress <> "fail" Then
            Dim clickedButton As Button = TryCast(sender, Button)
            Dim processNumber As Short = clickedButton.Parent.TabIndex
            textBoxBinary(processNumber).Text = fileAddress
        End If

        HandleButton()
    End Sub

    Private Sub ButtonDownload_Click(sender As System.Object, e As System.EventArgs) _
        Handles buttonDownload01.Click,
                buttonDownload02.Click,
                buttonDownload03.Click,
                buttonDownload04.Click,
                buttonDownload05.Click,
                buttonDownload06.Click,
                buttonDownload07.Click,
                buttonDownload08.Click,
                buttonDownload09.Click,
                buttonDownload10.Click

        Dim clickedButton As Button = TryCast(sender, Button)
        Dim processNumber As Short = clickedButton.Parent.TabIndex

        runThread(processNumber) = New Thread(Sub() RunDownload(processNumber))
        runThread(processNumber).Start()
    End Sub

    Private Sub RunDownload(i As Int16)
        Dim port As String = GetPort(i)
        Dim baudRate As String = GetBaudRate(i)
        Dim binary As String = getBinary(i)

        Try
            Dim arguments As String = Nothing
            Dim cmdProcess As New Process()
            Dim startInfo As New ProcessStartInfo()

            If binary.IndexOf(".bin") <> -1 Then    '바이너리가 bin 파일인 경우
                arguments = "-c port=" & port & " br=" & baudRate & " -rdu" & " -w " & binary & " 0x08000000 -v -ob RDP=0xBB"
            Else                                    '바이너리가 hex 파일인 경우
                arguments = "-c port=" & port & " br=" & baudRate & " -rdu" & " -w " & binary & " -ob RDP=0xBB"
            End If
            startInfo.FileName = """" & downloaderFile & """"
            startInfo.Arguments = arguments
            startInfo.UseShellExecute = False
            startInfo.RedirectStandardOutput = True
            startInfo.CreateNoWindow = True

            ClearTextBoxCmdWindow(i)

            cmdProcess.StartInfo = startInfo
            cmdProcess.Start()
            UpdateTextBoxInfo(i, "STARTING")

            ' 표준 출력 스트림 리더 가져오기
            Dim reader As StreamReader = cmdProcess.StandardOutput
            Dim line As String

            ' 프로세스가 끝날 때까지 또는 스트림의 끝에 도달할 때까지 한 줄씩 읽기
            While Not reader.EndOfStream
                line = reader.ReadLine().Trim
                UpdateTextBoxCmdWindow(i, Environment.NewLine & line)
            End While

            cmdProcess.WaitForExit()
            UpdateTextBoxInfo(i, "FINISHED")

        Catch ex As Exception
            MsgBox(ex.Message)
        End Try
    End Sub

    Private Function GetPort(i As Int16) As String
        Dim port As String
        If comboBoxPort(i).InvokeRequired Then
            comboBoxPort(i).Invoke(Sub()
                                       port = comboBoxPort(i).Text
                                   End Sub)
        Else
            port = comboBoxPort(i).Text
        End If
        Return port
    End Function

    Private Function GetBaudRate(i As Int16) As String
        Dim baudRate As String
        If comboBoxBaudRate.InvokeRequired Then
            comboBoxBaudRate.Invoke(Sub()
                                        BaudRate = comboBoxBaudRate.Text
                                    End Sub)
        Else
            BaudRate = comboBoxBaudRate.Text
        End If
        Return baudRate
    End Function

    Private Function getBinary(i As Int16) As String
        Dim binary As String
        If textBoxBinary(i).InvokeRequired Then
            textBoxBinary(i).Invoke(Sub()
                                        binary = """" & textBoxBinary(i).Text & """"
                                    End Sub)
        Else
            binary = """" & textBoxBinary(i).Text & """"
        End If
        Return binary
    End Function

    Private Sub UpdateTextBoxCmdWindow(i As Int16, state As String)
        If textBoxCmdWindow(i).InvokeRequired Then
            textBoxCmdWindow(i).Invoke(Sub()
                                           '처음 메시지 출력할 때 info textbox 업데이트
                                           If textBoxCmdWindow(i).Text.Length = 0 Then
                                               UpdateTextBoxInfo(i, "DOWNLOADING")
                                           End If
                                           textBoxCmdWindow(i).AppendText(state)
                                       End Sub)
        Else
            '처음 메시지 출력할 때 info textbox 업데이트
            If textBoxCmdWindow(i).Text.Length = 0 Then
                UpdateTextBoxInfo(i, "DOWNLOADING")
            End If
            textBoxCmdWindow(i).AppendText(state)
        End If
    End Sub

    Private Sub ClearTextBoxCmdWindow(i As Int16)
        If textBoxCmdWindow(i).InvokeRequired Then
            textBoxCmdWindow(i).Invoke(Sub()
                                           textBoxCmdWindow(i).Clear()
                                       End Sub)
        Else
            textBoxCmdWindow(i).Clear()
        End If
    End Sub

    Private Sub UpdateTextBoxInfo(i As Int16, state As String)
        If textBoxInfo(i).InvokeRequired Then
            textBoxInfo(i).Invoke(Sub()
                                      textBoxInfo(i).Text = state
                                  End Sub)
        Else
            textBoxInfo(i).Text = state
        End If
    End Sub

    Private Sub ClearTextBoxInfo(i As Int16)
        If textBoxInfo(i).InvokeRequired Then
            textBoxInfo(i).Invoke(Sub()
                                      textBoxInfo(i).Text = "READY"
                                  End Sub)
        Else
            textBoxInfo(i).Text = "READY"
        End If
    End Sub

    Private Sub buttonClean_Click(sender As Object, e As EventArgs) Handles buttonClean.Click
        Initialize()
    End Sub

End Class