using AR;
using ENIG;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace SampleProject
{
    enum messageType
    {
        rx,
        tx,
        normal,
        error
    }
    public partial class Form1 : Form
    {

        System.IO.Ports.SerialPort dev;
        EEProtocol proto;
        Dictionary<string, byte> idlist;
        public Form1()
        {
            InitializeComponent();
            this.Text = $"Amkor ENIG Protocol Test (PanID:46A5, CH:17)";
            proto = new EEProtocol();
            proto.OnDataReceived += Proto_OnDataReceived;
            proto.OnMessage += Proto_OnMessage;
            dev = new System.IO.Ports.SerialPort();
            dev.ReadTimeout = 2000;
            dev.WriteTimeout = 1000;
            dev.DataReceived += (s1, e1) =>
            {
                var buffer = new byte[dev.BytesToRead];
                dev.Read(buffer, 0, buffer.Length);
                proto.ProcessReceivedData(buffer);
            };

            idlist = new Dictionary<string, byte>();
            idlist.Add("ACS", 0);
            idlist.Add("AGV1", 10);
            idlist.Add("AGV2", 11);
            idlist.Add("BUFFER1", 20);
            idlist.Add("BUFFER2", 21);
            idlist.Add("BUFFER3", 22);
            idlist.Add("BUFFER4", 23);
            idlist.Add("BUFFER5", 24);
            idlist.Add("DOOR", 30);

            this.cmbid.Items.Clear();
            foreach (var item in idlist)
                cmbid.Items.Add($"{item.Key}");

            tbCmd.Text = "FF";
            tbmsg.Text = string.Empty;
        }

        private void Proto_OnDataReceived(object sender, EEProtocol.DataEventArgs e)
        {
            var hexstrRaw = e.ReceivedPacket.RawData.HexString();
            var hexstr = e.ReceivedPacket.Data.HexString();
            var cmd = e.ReceivedPacket.Command.ToString("X2");
            var id = e.ReceivedPacket.ID.ToString("X2");
            AddMessage($"{hexstrRaw}\nID:{id},CMD:{cmd},DATA:{hexstr}", messageType.rx);
        }
        private void Proto_OnMessage(object sender, EEProtocol.MessageEventArgs e)
        {
            AddMessage(e.Message);
        }

        void AddMessage(string msg, messageType type = messageType.normal)
        {
            if (this.InvokeRequired)
            {
                this.BeginInvoke(new Action(() => AddMessage(msg, type)));
                return;
            }

            if (type == messageType.rx)
            {
                rtRx.AppendText($"<{DateTime.Now.ToString("HH:mm:ss")} RX> {msg}\r\n");
                rtRx.ScrollToCaret();
            }
            else if (type == messageType.tx)
            {
                rtTx.AppendText($"<{DateTime.Now.ToString("HH:mm:ss")} TX> {msg}\r\n");
                rtTx.ScrollToCaret();
            }
            else
            {
                rtMsg.AppendText($"<{DateTime.Now.ToString("HH:mm:ss")} > {msg}\r\n");
                rtMsg.ScrollToCaret();
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            cmbport.Items.Clear();
            foreach (var item in System.IO.Ports.SerialPort.GetPortNames())
            {
                cmbport.Items.Add(item);
            }
            if (Pub.Setting.LastPort.isEmpty() == false) cmbport.Text = Pub.Setting.LastPort;
            else if (cmbport.Items.Count > 0) cmbport.SelectedIndex = 0;

            if (Pub.Setting.LastBaud.isEmpty() == false) tbbaud.Text = Pub.Setting.LastBaud;
            if (cmbid.Items.Count > 0) cmbid.SelectedIndex = 0;
            LoadCmds();
            this.timer1.Start();
        }

        private void btconnect_Click(object sender, EventArgs e)
        {
            var port = cmbport.Text.Trim();
            var baud = tbbaud.Text.toInt();

            //setting save
            Pub.Setting.LastPort = port;
            Pub.Setting.LastBaud = baud.ToString();
            Pub.Setting.Save();

            if (dev.IsOpen)
            {
                dev.Close();
                AddMessage("port closed");
            }
            else
            {
                try
                {
                    this.dev.PortName = port;
                    this.dev.BaudRate = baud;
                    dev.Open();
                    AddMessage("port opened");
                }
                catch (Exception ex)
                {
                    AddMessage(ex.Message, messageType.error);
                }
            }


        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            sbPort.Text = $"{dev.PortName}:{dev.BaudRate} {(dev.IsOpen ? "Open" : "Closed")}";
        }

        private void tbmsg_TextChanged(object sender, EventArgs e)
        {

        }

        private void btsend_Click(object sender, EventArgs e)
        {
            //send to device
            var msg = tbmsg.Text.Trim();
            var id = this.idlist[cmbid.Text];
            var cmdHex = this.tbCmd.Text.Trim();
            byte cmd = Convert.ToByte(cmdHex, 16);
            byte[] msgBytes = Encoding.ASCII.GetBytes(msg);      // 메시지를 byte 배열로 변환

            var data = proto.CreatePacket(id, cmd, msgBytes);
            SendToDevice(data);
        }

        void SendToDevice(byte[] packet)
        {
            if (dev.IsOpen == false)
            {
                AddMessage("port closed", messageType.error);
            }
            else
            {
                dev.Write(packet, 0, packet.Length);
                var hexstring = packet.HexString();
                AddMessage(hexstring, messageType.tx);
            }

        }

        private void btsim_Click(object sender, EventArgs e)
        {
            //packet test
            var msg = tbmsg.Text.Trim();
            var id = this.idlist[cmbid.Text];
            var cmdHex = this.tbCmd.Text.Trim();
            byte cmd = Convert.ToByte(cmdHex, 16);     // 16진수 문자열을 byte로 변환
            byte[] msgBytes = Encoding.ASCII.GetBytes(msg);  // 메시지를 byte 배열로 변환

            var data = proto.CreatePacket(id, cmd, msgBytes);
            this.proto.PacketTest(data);
        }
        string fn = "cmds.rtf";
        private void btSave_Click(object sender, EventArgs e)
        {
            System.IO.File.WriteAllText("cmds.rtf", rtCmd.Rtf, System.Text.Encoding.Default);
        }

        private void btload_Click(object sender, EventArgs e)
        {
            LoadCmds();
        }

        void LoadCmds()
        {
            var fi = new System.IO.FileInfo("cmds.rtf");
            if (fi.Exists == false)
            {
                AddMessage("no cmds file", messageType.error);
                return;
            }
            var data = System.IO.File.ReadAllText("cmds.rtf", System.Text.Encoding.Default);
            rtCmd.Rtf = data;
        }
    }
}
