using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.IO.Ports;
using System.Threading;

namespace iSTP_Tools
{
    public class PowerSupplyController
    {
        PowerSupplyWindow _View;
        SerialPort PsPort;
        int commDelay = 100;
        
        public PowerSupplyController()
        {
            _View = new PowerSupplyWindow();
            _View.SetController(this);
            PsPort = new SerialPort();
            PsPort.ReadTimeout = 500;
        }

        public void ShowControl()
        {
            _View.ShowDialog();
        }

        public bool Connect()
        {
            bool retVal = false;
            if (PsPort == null)
                PsPort = new SerialPort();

            if (!PsPort.IsOpen)
            {
                string port = _View.ComPort.Trim();
                if (port == "")
                    return false;
                PsPort.PortName = port; 
                PsPort.DataBits = 8;
                PsPort.StopBits = StopBits.One;
                PsPort.BaudRate = 9600;
                PsPort.Parity = Parity.None;
                PsPort.Handshake = Handshake.None;
                try
                {
                    PsPort.Open();
                    PsPort.DiscardInBuffer();
                    _View.ChangeConnectionLabel("Disconnect");
                    _View.EnableControls(true);
                    retVal = true;
                }
                catch (Exception ex)
                {
                    Console.WriteLine("problem openning PowerSupply port: {0}", ex.ToString());
                }
            }
            else
            {
                try
                {
                    PsPort.Close();
                    _View.ChangeConnectionLabel("Connect");
                    _View.EnableControls(false);
                    retVal = true;
                }
                catch (Exception ex)
                {
                    Console.WriteLine("problem closing PowerSupply port: {0}", ex.ToString());
                }
            }
            if (retVal)
            {
                _View.Voltage = GetVoltage();
                Thread.Sleep(commDelay);
                _View.Current = GetCurrent();
                Thread.Sleep(commDelay);
                _View.SetOutputIndication(GetOutput());
            }
            return retVal;
        }

        private bool GetOutput()
        {
            bool retVal = false;
            byte response;
            if (PsPort.IsOpen)
            {
                PsPort.Write("STATUS?");
                Thread.Sleep(commDelay);
                response = GetResponse1B();
                retVal = (response & 0x40) > 0;
            }
            return retVal;
        }

        public void EnableOutput()
        {
            if (PsPort.IsOpen)
            {
                PsPort.Write("OUT1");
                Thread.Sleep(commDelay);
                _View.SetOutputIndication(GetOutput());
            }
        }

        public void DisableOutput()
        {
            if (PsPort.IsOpen)
            {
                PsPort.Write("OUT0");
                Thread.Sleep(commDelay);
                _View.Voltage = GetVoltage();
                Thread.Sleep(commDelay);
                _View.Current = GetCurrent();
                Thread.Sleep(commDelay);
                _View.SetOutputIndication(GetOutput());
            }
        }

        public void SetOutput(float volt, float amp)
        {
            if (PsPort.IsOpen)
            {
                string command = String.Format("VSET1:" + volt.ToString("00.00"));
                PsPort.Write(command);
                Thread.Sleep(commDelay);
                command = String.Format("ISET1:" + amp.ToString("0.000"));
                PsPort.Write(command);
                Thread.Sleep(commDelay);
                _View.Voltage = GetVoltage();
                Thread.Sleep(commDelay);
                _View.Current = GetCurrent();
                Thread.Sleep(commDelay);
                _View.SetOutputIndication(GetOutput());
            }
        }

        public float GetVoltage()
        {
            float retVal = 0f;
            //return retVal;
            if (PsPort.IsOpen)
            {
                PsPort.Write("VSET1?");
                Thread.Sleep(commDelay);
                string response = GetResponse();
                float.TryParse(response, out retVal);
            }
            return retVal;
        }

        public float GetCurrent()
        {
            float retVal = 0f;
            if (PsPort.IsOpen)
            {
                PsPort.Write("ISET1?");
                Thread.Sleep(commDelay);
                string response = GetResponse();
                float.TryParse(response, out retVal);
            }
            return retVal;
        }

        private string GetResponse()
        {
            string response = "";
            byte[] buffer = new byte[30];
            int i = 0;
            try
            {
                while (PsPort.BytesToRead > 0)
                {
                    int toRead = PsPort.ReadBufferSize;
                    if (i + toRead > 30)
                        toRead = 30 - i;
                    if (toRead > 0)
                    {
                        PsPort.Read(buffer, i, toRead);
                        i += toRead;
                    }
                    else
                        break;
                }
            }
            catch(Exception ex)
            {
                Console.WriteLine("PowerSupply serial line issue: "+ex.ToString());
            }
            response = System.Text.Encoding.ASCII.GetString(buffer, 0, i);
            return (response);
        }

        private byte GetResponse1B()
        {
            byte[] buffer = new byte[30];
            int i = 0;
            try
            {
                PsPort.Read(buffer, i, 1);
            }
            catch (Exception ex)
            {
                Console.WriteLine("PowerSupply serial line issue: " + ex.ToString());
            }
            return (buffer[0]);
        }
    }
}
