using System;
using System.IO.Ports;
using System.Threading;

namespace GatewayCommon
{
    public class DeviceControl : System.IDisposable
    {
        private SerialPort port;

        public delegate void DeviceEventHandler(string message);
        public delegate void DeviceErrorHandler(string message, Exception exception);

        public event DeviceErrorHandler Error;
        public event DeviceEventHandler CommandReceived;

        public bool IsAlive
        {
            get;
            private set;
        }
        public DeviceControl(string portNumber)
        {
            port = new SerialPort();
            port.PortName = portNumber;
            port.BaudRate = 115200;
            port.Parity = Parity.None;
            port.DataBits = 8;
            port.StopBits = StopBits.One;
            port.Handshake = Handshake.RequestToSendXOnXOff;
            port.DtrEnable = true;
            port.RtsEnable = true;
            port.NewLine = System.Environment.NewLine;
            this.Open();
        }
        public DeviceControl(SerialPort serialPort)
        {
            port = serialPort;
            this.Open();
        }
        ~DeviceControl()
        {
            this.Close();
        }
        public void Dispose()
        {
            this.Close();
        }
        public void Open()
        {
            if (port.IsOpen == false)
            {
                try
                {
                    port.Open();
                    port.DataReceived += new SerialDataReceivedEventHandler(ReadData);
                    IsAlive = true;
                }
                catch (Exception ex)
                {
                    if (Error != null)
                        Error("Device is busy", ex);
                }
            }
        }
        public void Close()
        {
            IsAlive = false;
            if (port.IsOpen == true)
                port.Close();
        }
        private void ReadData(object sender, SerialDataReceivedEventArgs e)
        {
            string portMessage = string.Empty;
            byte[] rxBuffer = new byte[port.ReadBufferSize + 1];
            if (port.BytesToRead != 0 & port.IsOpen)
            {
                while (port.BytesToRead != 0)
                {
                    port.Read(rxBuffer, 0, port.ReadBufferSize);
                    portMessage += System.Text.Encoding.ASCII.GetString(rxBuffer);
                }
                if (CommandReceived != null)
                    CommandReceived(portMessage);
                portMessage = string.Empty;
                rxBuffer = new byte[port.ReadBufferSize + 1];
            }
        }
        public bool SendData(string Command)
        {
            if (port.IsOpen && !string.IsNullOrEmpty(Command))
            {
                port.WriteLine(Command);
                return true;
            }
            return false;
        }
    }
}
