using System;
using System.IO.Ports;
using System.Text;
using System.Threading;
using HWModules;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SWModules;

namespace CPFUnitTests.PowerSwitchBoard
{
    /// <summary>
    /// This Unit Test was written to test the SN1 configuration 
    /// as manufactured in Fall 2017. The configuration is an all
    /// native UART board for RS232 channels. Energy monitors will
    /// be tested but may not be used. 
    /// 
    /// Some tests that don't require external wiring will just
    /// occur, and others will prompt through the debugging 
    /// console for the opertor to press the LDR0 button on the
    /// motherboard. 
    /// 
    /// -EJM
    /// </summary>
    [TestClass]
    public class UnitTest_PSB_SN1
    {
        private HWModules.MotherBoard mb;
        private bool _runonce = false;
        private void Init()
        {
            if (!_runonce)
            {
                mb = HWModules.MotherBoard.Instance;
                _runonce = true;
            }

        }

        private void WaitForLdr0()
        {
            Debug.Print("Press LDR0 Button to Continue... \n");
            while (!mb.Ldr0Pushed)
                Thread.Sleep(100);
            //Clear the state
            mb.Ldr0Pushed = false;
        }

        //[TestMethod]
        //public void TestSwitchPowerOnAllPorts()
        //{
        //    Init();

        //    mb.Enable12V();
        //    mb.Enable5V();

        //    Debug.Print("\n\nTESTING CH4 SLOT 2 PORT A\n");
        //    WaitForLdr0();
        //    mb.EnableChannelPower(4);
        //    WaitForLdr0();
        //    mb.DisableChannelPower(4);

        //    Debug.Print("\n\nTESTING CH5 SLOT 2 PORT B\n");
        //    WaitForLdr0();
        //    mb.EnableChannelPower(5);
        //    WaitForLdr0();
        //    mb.DisableChannelPower(5);

        //    Debug.Print("\n\nTESTING CH6 SLOT 2 PORT C\n");
        //    WaitForLdr0();
        //    mb.EnableChannelPower(6);
        //    WaitForLdr0();
        //    mb.DisableChannelPower(6);

        //    mb.Disable12V();
        //    mb.Disable5V();
        //}

        [TestMethod]
        public void TestEnergyMonitorAndPowerSlot2A()
        {
            Init();

            mb.Enable12V();
            mb.Enable5V();
            mb.EnableChannelPower(4);

            Debug.Print("\n\nEM Slot2A TEST");
            WaitForLdr0();
            
            EnergyMonitorLTC2946 em = new EnergyMonitorLTC2946(new I2CDevice.Configuration(0xCE >> 1, 400), EnergyMonitorLTC2946.VoltageSource.Adin, 0.005865, 1.250,2);
            em.ReadCtlARegister();

            for (int i=0; i<10; i++)
            {
                EnergyMonitorLTC2946.EM_VandI data = em.getVandI();
                Debug.Print("SLOT2A DATA V/I:" + data.volts.ToString() + " / " + data.amps.ToString());
                Thread.Sleep(100);
            }

            Debug.Print("Please Attempt to overload the circuit (>2.5A)");
            WaitForLdr0();

            mb.DisableChannelPower(4);
            mb.Disable12V();
            mb.Disable5V();
        }

        [TestMethod]
        public void TestEnergyMonitorAndPowerSlot2B()
        {
            Init();

            mb.Enable12V();
            mb.Enable5V();
            mb.EnableChannelPower(5);
            
            Debug.Print("\n\nEM Slot2B TEST");
            WaitForLdr0();

            EnergyMonitorLTC2946 em = new EnergyMonitorLTC2946(new I2CDevice.Configuration(0xD2 >> 1, 400), EnergyMonitorLTC2946.VoltageSource.Adin, 0.005865, 0.625,2);
            em.ReadCtlARegister();
            
            for (int i=0; i<10; i++)
            {
                EnergyMonitorLTC2946.EM_VandI data = em.getVandI();
                Debug.Print("SLOT2B DATA V/I:" + data.volts.ToString() + " / " + data.amps.ToString());
                Thread.Sleep(100);
            }

            Debug.Print("Please Attempt to overload the circuit (>1.25A)");
            WaitForLdr0();

            mb.DisableChannelPower(5);
            mb.Disable12V();
            mb.Disable5V();
        }

        [TestMethod]
        public void TestEnergyMonitorAndPowerSlot2C()
        {
            Init();

            mb.Enable12V();
            mb.Enable5V();
            mb.EnableChannelPower(6);
            
            Debug.Print("\n\nEM Slot2C TEST");
            WaitForLdr0();

            EnergyMonitorLTC2946 em = new EnergyMonitorLTC2946(new I2CDevice.Configuration(0xD8 >> 1, 400), EnergyMonitorLTC2946.VoltageSource.Adin, 0.005865, 0.625, 2);
            em.ReadCtlARegister();

            for (int i=0; i<10; i++)
            {
                EnergyMonitorLTC2946.EM_VandI data = em.getVandI();
                Debug.Print("SLOT2C DATA V/I:" + data.volts.ToString() + " / " + data.amps.ToString());
                Thread.Sleep(100);
            }

            Debug.Print("Please Attempt to overload the circuit (>1.25A)");
            WaitForLdr0();

            mb.DisableChannelPower(6);
            mb.Disable12V();
            mb.Disable5V();
        }


        [TestMethod]
        public void TestNativeUartSlot2A()
        {
            Init();
            Debug.Print("\nNative UART Slot 2A Test // Connect to J3\n");
            WaitForLdr0();

            mb.Enable12V();mb.Enable5V();
            mb.EnableChannelPower(4);
            SerialPort port = new SerialPort("COM3", 115200);
            port.DataReceived += PrintPortData;
            port.Open();
            port.Write(msg,0,msg.Length);

            Debug.Print("Test Running...");

            port.Write(msg,0,msg.Length);
            WaitForLdr0();

            port.Close();
            mb.DisableChannelPower(4);
            mb.Disable12V();
            mb.Disable5V();
        }

        [TestMethod]
        public void TestNativeUartSlot2B()
        {
            Init();
            Debug.Print("\nNative UART Slot 2B Test // Connect to J3\n");
            WaitForLdr0();

            mb.Enable12V();mb.Enable5V();
            mb.EnableChannelPower(5);
            SerialPort port = new SerialPort("COM5", 115200);
            port.DataReceived += PrintPortData;
            port.Open();

            Debug.Print("Test Running...");

            port.Write(msg,0,msg.Length);
            WaitForLdr0();

            port.Close();
            mb.DisableChannelPower(5);
            mb.Disable12V();
            mb.Disable5V();
        }

        private static readonly byte[] msg = Encoding.UTF8.GetBytes("hi there\n");
        [TestMethod]
        public void TestNativeUartSlot2C()
        {
            Init();
            Debug.Print("\nNative UART Slot 2C Test // Connect to J4\n");
            WaitForLdr0();

            mb.Enable12V();mb.Enable5V();
            mb.EnableChannelPower(6);
            SerialPort port = new SerialPort("COM6", 115200);
            port.DataReceived += PrintPortData;
            port.Open();

            Debug.Print("Test Running...");

            port.Write(msg,0,msg.Length);

            WaitForLdr0();

            port.Close();
            mb.DisableChannelPower(6);
            mb.Disable12V();
            mb.Disable5V();
        }

        private StringBuilder sb; 
        private void PrintPortData(Object obj, SerialDataReceivedEventArgs e)
        {
            SerialPort port = (SerialPort)obj;

            if (sb == null) 
                sb = new StringBuilder();
            sb.Clear();

            while (port.BytesToRead > 0)
                sb.Append(port.ReadByte());

            Debug.Print("GOT DATA: "+sb.ToString()+" [EOL]\n");
        }

        //[TestMethod]
        //public void TestI2CUartSlot3A()
        //{
        //    Init();
        //    mb.EnableChannelPower(7);
           
            
        //    I2CUartBridge ub = new I2CUartBridge(new I2CDevice.Configuration(0x60 >> 1, 400));
        //    for (int i=0; i<10; i++)
        //    {
        //        ub.get_i2c_buffer();
        //        byte[] msgBytes = UTF8Encoding.UTF8.GetBytes("hello world\n\r");

        //        ub.i2cprint(msgBytes, msgBytes.Length);
        //        Thread.Sleep(1000);
        //    }
        //    mb.DisableChannelPower(7);

        //}

        //[TestMethod]
        //public void TestI2CUartSlot3B()
        //{
        //    Init();
        //    mb.EnableChannelPower(8);
        //    I2CUartBridge ub = new I2CUartBridge(new I2CDevice.Configuration(0x62 >> 1, 400));
        //    for (int i=0; i<10; i++)
        //    {
        //        ub.get_i2c_buffer();
        //        byte[] msgBytes = UTF8Encoding.UTF8.GetBytes("hello world\n\r");

        //        ub.i2cprint(msgBytes, msgBytes.Length);
        //        Thread.Sleep(1000);
        //    }
        //    mb.DisableChannelPower(8);
        //}
        
        //[TestMethod]
        //public void TestI2CUartSlot3C()
        //{
        //    Init();
        //    MotherBoard mb = MotherBoard.Instance;
        //    mb.EnableChannelPower(9);

        //    I2CUartBridge ub = new I2CUartBridge(new I2CDevice.Configuration(0x68 >> 1, 400),3);
        //    int i = 0;
        //    while (i++ < 100)
        //    {
        //        ub.get_i2c_buffer();
        //        byte[] msgBytes = UTF8Encoding.UTF8.GetBytes("hello world\n\r");

        //        ub.i2cprint(msgBytes, msgBytes.Length);
        //        Thread.Sleep(1000);
        //    }
        //    mb.DisableChannelPower(9);

        //}
        
        //[TestMethod]
        //public void TestI2CSerialPortSlot3C()
        //{
        //    Init();
        //    MotherBoard mb = MotherBoard.Instance;
        //    mb.EnableChannelPower(9);

        //    var port = new I2CSerialPort("COM9");
        //    port.DataReceived += port_DataReceived;
        //    port.Open();

        //    int i = 30;
        //    var msgBytes = Encoding.UTF8.GetBytes("Hello Port 3c\r\n");

        //    while (--i > 0)
        //    {
        //        port.Write(msgBytes, 0, msgBytes.Length);
        //        Thread.Sleep(1000);
        //    }
        //    mb.DisableChannelPower(9);

        //}

        private StringBuilder _sbTemp = new StringBuilder();
        private void port_DataReceived(object sender, EventArgs e)
        {
            var inbuff = new byte[1024];

            var port = (I2CSerialPort) sender;
            port.Read(inbuff, 0, port.BytesToRead);
            _sbTemp.Append(SafeEncoding.GetChars(inbuff));
            Debug.Print("Got Line: " + _sbTemp.ToString());

        }
    
    }
}
