using iq2dev.com.iqCommLib.DataTypes;
using iq2dev.com.IQCommLib;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace iq2dev.com.iqCommLib.EMC
{
    public struct EmcCountersMasterTester
    {
        public UInt32 InvalidResponseCounter;
        public UInt32 MseqCounter;

        public EmcCountersMasterTester(
            List<byte> invalidCounterData,
            List<byte> mseqCounterData)
        {
            InvalidResponseCounter = BitConverter.ToUInt32(invalidCounterData.ToArray());
            MseqCounter = BitConverter.ToUInt32(mseqCounterData.ToArray());
        }
    }

    static internal class EmcMasterTester
    {
        private static readonly Dictionary<IOLBaudrate, byte>
            CycleTimeForEMCTest = new Dictionary<IOLBaudrate, byte>() {
                { IOLBaudrate.COM3, 0x04 }, // 0.4 ms
                { IOLBaudrate.COM2, 0x17 }, // 2.3 ms
                { IOLBaudrate.COM1, 0x5D }  // 18.0 ms
            };

        private enum EMCMstTesterState
        { Inactive = 0, Init = 1, Active = 2 }

        static public void StartAsMasterTester(
            this ProtocolCommunicator protocolCommunicator,
            IOLBaudrate baudrate,
            byte expectedResponse)
        {
            protocolCommunicator.writeIQCommPar(IQPar.IQParIQIOperMode, new List<byte>() { (byte)IQOperMode.IOLDevice });

            GenericDeviceConfig config = new GenericDeviceConfig();
            config.Baudrate = baudrate;
            config.ODSizePreoperate = 1;
            config.ODSizeOperate = 1;
            config.IsPDInLengthBytes = false;
            config.IsPDOutLengthBytes = false;
            config.PDInLength = 8;
            config.PDOutLength = 8;
            config.MinCycleTime = CycleTimeForEMCTest[baudrate];
            config.MinCycleTimeBase = (IOLCycTimeBase)(config.MinCycleTime >> 6);

            config.Submit();
            config.Download(protocolCommunicator);

            SetEMCMstTesterState(protocolCommunicator, EMCMstTesterState.Init);
        }

        static private void SetEMCMstTesterState(this ProtocolCommunicator protocolCommunicator, EMCMstTesterState state)
        {
            var data = new List<byte>() { (byte)state };
            var seed = new byte[4];
            var random = new Random();
            random.NextBytes(seed);
            data.AddRange(seed);
            protocolCommunicator.writeIQCommPar(IQPar.IQParDevEMCMstTestMode, data);
        }

        static public void ResetCounters(this ProtocolCommunicator protocolCommunicator)
        {
            protocolCommunicator.writeIQCommPar(IQPar.IQParDevEMCMstTestCounters, new List<byte>() { 0 });
        }

        static public EmcCountersMasterTester ReadCounters(this ProtocolCommunicator protocolCommunicator)
        {
            var counters = protocolCommunicator.readIQCommPar(IQPar.IQParDevEMCMstTestCounters);
            var invalidCounterData = counters.GetRange(0, 4);
            invalidCounterData.Reverse();
            var mseqCounterData = counters.GetRange(4, 4);
            mseqCounterData.Reverse();
            return new EmcCountersMasterTester(invalidCounterData, mseqCounterData);
        }
    }
}
