using System;
using System.Collections.Generic;
using System.Text;
using System.IO.Ports;

namespace MoveTest
{
    /// <summary>
    /// This class provides methods to send and recieve data over a serial port
    /// </summary>
    class SerialCommunications : IDisposable
    {
        /// <summary>Base class for serial communications, shouldn't really be public</summary>
        public SerialPort serialPort;

        /// <summary>Creates the serial port and sets it up</summary>
        /// <param name="portName">Text name of the serial port, for example COM17</param>
        public SerialCommunications(string portName, int baudRate)
        {
            serialPort = new SerialPort(portName, baudRate,         //Creates serial port with given
                Parity.None, 8, StopBits.One);                      //name and some default values
            serialPort.ErrorReceived += new SerialErrorReceivedEventHandler(serialPort_ErrorReceived);
            
            serialPort.ReadTimeout = 10;
            //serialPort.Handshake = Handshake.RequestToSend;
            serialPort.ReceivedBytesThreshold = 4;
            if (serialPort.IsOpen)          //Check if serial port already open
            {
                serialPort.Close();         //If so, close it, shouldn't really happen
                System.Windows.Forms.MessageBox.Show
                    ("Serial port already open");
            }
            
            serialPort.Open();              //Open the serial port
        }

        void serialPort_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
        {
               throw new NotImplementedException();
               System.Windows.Forms.MessageBox.Show(e.EventType.ToString());
        }

        /// <summary>Sends data to the serial port</summary>
        /// <param name="message">Text string to send</param>
        public void Send(string message)
        {
            serialPort.RtsEnable = true;

            DateTime startTime = DateTime.UtcNow;
            DateTime currentTime;

            while (!serialPort.CtsHolding)
            {
                currentTime = DateTime.UtcNow;

                if ((currentTime - startTime).TotalMilliseconds > 100)
                {
                    System.Windows.Forms.MessageBox.Show("Could not send " + message);
                    break;
                }
            }

            serialPort.RtsEnable = false;

            serialPort.Write(message);
        }

        /// <summary>Sends data to the serial port</summary>
        /// <param name="buffer">Byte array to send</param>
        public void Send(byte[] buffer)
        {
            DateTime startTime = DateTime.UtcNow;
            //DateTime currentTime;
            
            serialPort.BaseStream.Flush();

            for (int i = 0; i < buffer.Length; ++i)
            {
                serialPort.RtsEnable = true;
                
                while (!serialPort.CtsHolding)
                {
                    //currentTime = DateTime.UtcNow;

                    //if ((currentTime - startTime).TotalMilliseconds > 500)
                    //{
                        //System.Windows.Forms.MessageBox.Show("Could not send " + ASCIIEncoding.ASCII.GetString(buffer)); //buffer[i].ToString());
                        //break;
                    //}

                    System.Windows.Forms.Application.DoEvents();
                }
                
                //serialPort.RtsEnable = false;
                serialPort.Write(buffer, i, 1);
                                
            }
        }

        /// <summary>Sends data to the serial port</summary>
        /// <param name="buffer">Byte array to send</param>
        /// <param name="offset">The offset into the array to write from</param>
        /// <param name="count">Number of bytes to send</param>
        public void Send(byte[] buffer, int offset, int count)
        {
            //serialPort.Write(buffer, offset, count);
        }

        /// <summary>Disposes the serial port</summary>
        public void Dispose()
        {
            serialPort.Close();
            serialPort.Dispose();
        }

    }
}
