using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//Add code
using System.Windows.Forms;
using System.IO;
using System.IO.Ports;
using System.Data;
using Jdas_Mbic;

namespace Jdas_Mbic
{
    class Serial
    {
        JdasMbic main_form;
        private System.IO.Ports.SerialPort serialPort;
        private Debug Debug = new Debug();    // Teminal Text Wnd Open
        public string Serial_Name { get => serialPort.PortName;  set => serialPort.PortName = value;}
        Data_Handler data_Handler = new Data_Handler();
        //FileDownload fileDownload;
        Update_Serial fileDownload = null;

        public void SetPortNameValues(object obj)
        {

            string[] ports = SerialPort.GetPortNames(); // load all name of com ports to string
            try
            {
                ((ComboBox)obj).Items.Clear(); //delete previous names in combobox items
            }
            catch { }


            ((ComboBox)obj).DataSource = null;
            foreach (string port in ports) //add this names to comboboxPort items
            {
                 ((ComboBox)obj).Items.Add(port); //if there are some com ports ,select first
            }
            if (((ComboBox)obj).Items.Count > 0)
            {
                ((ComboBox)obj).SelectedIndex = 0;
            }
            else
            {
                ((ComboBox)obj).Text = " "; //if there are no com ports ,write Empty
            }
        }
        public void Serial_Port_name_Set(ref ComboBox cb_port)
        {
            serialPort.PortName = Serial_Name = cb_port.SelectedItem.ToString();
        }
        public void Serial_Initialize(ref ComboBox cb_port)
        {
            int BaudRate = Convert.ToInt32(main_form.comboBox_baudrate.Text);
            this.serialPort = new System.IO.Ports.SerialPort();
            this.serialPort.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(this.Serial_DataRecvFunction);

            cb_port.BeginUpdate();
            foreach (string comport in SerialPort.GetPortNames())//foreach (string comport in SerialPort_TestProgram.GetPortNames())
            {
                cb_port.Items.Add(comport);
            }
            cb_port.EndUpdate();
            //SerialPort 초기 설정.
            //  serialPort.Encoding = Encoding.GetEncoding("Windows-1252");
            
            cb_port.DataSource =  SerialPort.GetPortNames();
            try
            {
                serialPort.PortName = Serial_Name = cb_port.SelectedItem.ToString();
                serialPort.BaudRate = (int)BaudRate;
                serialPort.DataBits = (int)8;
                serialPort.Parity = System.IO.Ports.Parity.None;
                serialPort.StopBits = StopBits.One;
            }
            catch { }

        }
        public void Serial_Setting()
        {
            int BaudRate = Convert.ToInt32(main_form.comboBox_baudrate.Text);
            this.serialPort = new System.IO.Ports.SerialPort();
            this.serialPort.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(this.Serial_DataRecvFunction);
            //SerialPort 초기 설정.
            //  serialPort.Encoding = Encoding.GetEncoding("Windows-1252");
            try
            {
                serialPort.BaudRate = (int)BaudRate;
                serialPort.DataBits = (int)8;
                serialPort.Parity = System.IO.Ports.Parity.None;
                serialPort.StopBits = StopBits.One;
            }
            catch { }

        }
        private delegate void StringSend(string Text);
        private delegate void ByteSend(byte[] Text);

        public string Str2hex(string strData,Boolean Compotable)
        {
            string resultHex = string.Empty;
            byte[] arr_byteStr = Encoding.Default.GetBytes(strData);

            foreach (byte byteStr in arr_byteStr)
            {
                if(Compotable == true)
                    resultHex += string.Format("{0:X2}", byteStr) + " ";
                else
                    resultHex += string.Format("{0:X2}", byteStr);
            }

            return resultHex;
        }

        static public byte[] Str2bytes(string byteData)
        {

#if false
            System.Text.ASCIIEncoding asencoding = new System.Text.ASCIIEncoding();
            return Encoding.Default.GetBytes(byteData);
#else 
            byte[] arr_byteStr = Encoding.Default.GetBytes(byteData);
            return arr_byteStr;
#endif
        }
        private delegate void BoolSet();
        public void Serial_DataRecvFunction(object sender, SerialDataReceivedEventArgs e)
        {
            string tmpSTR = "";
            Data_Handler data_Handler = new Data_Handler();
            int nLnegth = serialPort.BytesToRead;
            byte[] btdata = new byte[nLnegth];
            serialPort.Read(btdata, 0, nLnegth);
            main_form.Invoke(new BoolSet(main_form.RX_Light_ON));
            main_form.TX_RX_Light = true;
            if (this.Debug.Created && Debug.RadioButton_ascii.Checked == true)
            {
                string data = Encoding.Default.GetString(btdata);
                // string data = serialPort.ReadExisting();

                    if (Debug.RadioButton_ascii.Checked == true)
                        Debug.Invoke(new StringSend(Debug.Data_Recv_Str), data);
                    else
                        Debug.Invoke(new StringSend(Debug.Data_Recv_Str), Str2hex(data, true));

                data_Handler.Recv_dataCheck(this,this.main_form,this.fileDownload, btdata);
            }
            else
            {
                // 리스트 두개 사용

                if (nLnegth > 0)
                {
                    if (this.Debug.Created)
                    {
                        if (this.Debug.radioButton_ascii.Checked == true)
                        {
                            tmpSTR = Encoding.Default.GetString(btdata).TrimEnd('\0');
                        Debug.Invoke(new StringSend(Debug.Data_Recv_Str), Str2hex(tmpSTR, true));
                        }
                        else
                        {
                            Debug.Invoke(new ByteSend(Debug.Data_Recv_Hex), btdata);
                        }
                    }
                    else
                    {
                        if (this.Debug.Created)
                            Debug.Invoke(new ByteSend(Debug.Data_Recv_Hex), btdata);
                    }
                    // 이부분에서 데이타 처리하는 부분으로 전송하여 사용하면 됨
                }
                data_Handler.Recv_dataCheck(this, this.main_form,this.fileDownload, btdata);
            }
            /****
             *메모리 누수 방지용 코드
             */
            System.GC.Collect(0, GCCollectionMode.Forced);
            System.GC.WaitForFullGCComplete();
        }
        public byte Serial_PortOpen(ref Button Btn_Portonoff,ref ComboBox cb)
        {
            byte ret = 0;
            try
            {
                if (serialPort.IsOpen) { //When the port is open
                    serialPort.Close();
                    Btn_Portonoff.Text = "Port Open";
                    ret = 1;
                }
                else//When the port is close
                {
                    if (cb.Text != "")
                    {
                        //this.main_form.Invoke(new BoolSet(this.main_form.Serial_PortName_get));
                        Serial_Setting();
                        serialPort.PortName = cb.Text;
                        serialPort.Open();
                        Btn_Portonoff.Text = "Port Close";
                        Debug.Debug_Main_Form_Get(this.main_form);
                    }
                    else
                    {
                        MessageBox.Show("Port is not set");
                        ret = 1;
                    }
                }
               
            }
            catch
            {
                MessageBox.Show("already port open " + Serial_Name);
                ret = 2;
            }
            return ret;
        }
        public void Serial_TerminalOpen(object serial)
        {
            this.Debug.Serial_ClassSet(serial);
            try
            {
                this.Debug.Show();
            }
            catch
            {
                Debug = new Debug();
                this.Debug.Show();
            }
        }
#if false
        public void Serial_DataSend(byte[] data,int count)
        {
            try
            {
                serialPort.Write(data,0,data.Length);
                this.Debug.Data_Send(data, count);
                main_form.pictureBox_R_TX.Visible = false;
                main_form.pictureBox_G_TX.Visible = true;
            }
            catch (System.Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
#endif
        public void Serial_DataSend(byte[] buffer, int count)
        {
            try {
                serialPort.Write(buffer, 0, count);
                if (this.Debug.Created)
                    this.Debug.Data_Send(buffer, count);

                main_form.Invoke(new BoolSet(main_form.TX_Light_ON));
                main_form.TX_RX_Light = true;
            }
            catch
            {
                //MessageBox.Show("Port Open Failed!!!");
            }
        }
        public void FileDownloadClass_Set(object filedownload)
        {
            //this.fileDownload = (FileDownload)filedownload;
            this.fileDownload = (Update_Serial)filedownload;
        }
        public object FileDownloadClass_Get()
        {
            return this.fileDownload;
        }
        public void Test_Serial()
        {
            byte[] tempdata = new byte[1024];
            for (int i = 0; i < 255; i++)
            {

                tempdata[i] = Convert.ToByte(i);
                
                
            }
            this.serialPort.Write(tempdata, 0, 255);
            //this.serialPort.Write(tempdata.ToString());

        }
        public void debug_hextoasciiConvert()
        {
            if(this.Debug.Created)
                this.Debug.hex_to_ascii_radiobuttonConvert();
        }
        public void debug_asciitohexConvert()
        {
            if (this.Debug.Created)
                this.Debug.ascii_to_hex_radiobuttonConvert();
        }
        public void Serial_Main_Form_Get(object frm)
        {
            this.main_form = (JdasMbic)frm;
        }
    }
}
