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 EmcCounters
    {
        public UInt32 ChecksumErrorCounter;
        public UInt32 NoResponseCounter;
        public UInt32 InvalidResponseCounter;
        public UInt32 MseqCounter;

        public EmcCounters(
            List<byte> errorCounterData,
            List<byte> noResponseCounterData,
            List<byte> invalidCounterData,
            List<byte> mseqCounterData)
        {
            ChecksumErrorCounter = BitConverter.ToUInt32(errorCounterData.ToArray());
            NoResponseCounter = BitConverter.ToUInt32(noResponseCounterData.ToArray());
            InvalidResponseCounter = BitConverter.ToUInt32(invalidCounterData.ToArray());
            MseqCounter = BitConverter.ToUInt32(mseqCounterData.ToArray());
        }
    }

    public static class EmcDeviceTester
    {
        private const byte IQIOperMode_MstEMCTest = 0x09;

        static public bool IsSupported(this ProtocolCommunicator protocolCommunicator)
        {
            var gadgetInfo = new GadgetInfo(protocolCommunicator.readIQCommPar(IQPar.IQParProductInfo));
            return gadgetInfo.IsEmcSupported;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="protocolCommunicator"></param>
        /// <param name="cycleTime"></param>
        /// <param name="expectedResponse">Device min cycle time</param>
        static public void StartAsDeviceTester(
            this ProtocolCommunicator protocolCommunicator, 
            UInt16 cycleTime, 
            byte expectedResponse)
        {
            protocolCommunicator.writeIQCommPar(IQPar.IQParEMCCycleTime, new List<byte>(BitConverter.GetBytes(cycleTime).Reverse()));
            protocolCommunicator.writeIQCommPar(IQPar.IQParEMC_AvaitedTstRsp, new List<byte>() { expectedResponse });
            protocolCommunicator.writeIQCommPar(IQPar.IQParIQIOperMode, new List<byte>() { IQIOperMode_MstEMCTest });
        }

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

        static public EmcCounters ReadCounters(this ProtocolCommunicator protocolCommunicator)
        {
            // Read Checksum error counter:
            var errorCounterData = protocolCommunicator.readIQCommPar(IQPar.IQParEMC_CKSErrCounter);
            errorCounterData.Reverse();

            // Read No Response counter:
            var noResponseCounterData = protocolCommunicator.readIQCommPar(IQPar.IQParEMC_NoRspErrCounter);
            noResponseCounterData.Reverse();

            // Read Response error counter:
            var invalidCounterData = protocolCommunicator.readIQCommPar(IQPar.IQParEMC_RspErrCounter);
            invalidCounterData.Reverse();

            // Read M-sequence counter:
            var mseqCounterData = protocolCommunicator.readIQCommPar(IQPar.IQParEMC_MseqCounter);
            mseqCounterData.Reverse();

            return new EmcCounters(errorCounterData, noResponseCounterData, invalidCounterData, mseqCounterData);
        }
    }
}
