using NIDAQmx.DAQmxEnum;
using NIDAQmxConst;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace NIDAQmx
{
    public abstract class CIChannel : InChannel
    {
        internal CIChannel(DAQmxSession session) : base(session)
        {
            AttributeSession = new ChannelAttributeSession(session);
        }
        internal override ChannelAttributeSession AttributeSession { get; }
        public void ReadCounter(int numSampsPerChan,double timeout,ref double readArray,uint arraySizeInSamps,ref int sampsPerChanRead)
        {
            _Session.CheckResult(_Session.GetDelegate<Internal.DataRead.DAQmxReadCounterF64>()(_Session.TaskHandle, numSampsPerChan, timeout, ref readArray, arraySizeInSamps, ref sampsPerChanRead, IntPtr.Zero));
        }
        public void ReadCounter(int numSampsPerChan, double timeout, ref uint readArray, uint arraySizeInSamps, ref int sampsPerChanRead)
        {
            _Session.CheckResult(_Session.GetDelegate<Internal.DataRead.DAQmxReadCounterU32>()(_Session.TaskHandle, numSampsPerChan, timeout, ref readArray, arraySizeInSamps, ref sampsPerChanRead, IntPtr.Zero));
        }
        public void ReadCounter(int numSampsPerChan, double timeout,bool fillMode, ref double readArray, uint arraySizeInSamps, ref int sampsPerChanRead)
        {
            _Session.CheckResult(_Session.GetDelegate<Internal.DataRead.DAQmxReadCounterF64Ex>()(_Session.TaskHandle, numSampsPerChan, timeout,fillMode, ref readArray, arraySizeInSamps, ref sampsPerChanRead, IntPtr.Zero));
        }
        public void ReadCounter(int numSampsPerChan, double timeout,bool fillMode, ref uint readArray, uint arraySizeInSamps, ref int sampsPerChanRead)
        {
            _Session.CheckResult(_Session.GetDelegate<Internal.DataRead.DAQmxReadCounterU32Ex>()(_Session.TaskHandle, numSampsPerChan, timeout,fillMode, ref readArray, arraySizeInSamps, ref sampsPerChanRead, IntPtr.Zero));
        }
        public void ReadCounterScalar(double timeout, ref uint readArray)
        {
            _Session.CheckResult(_Session.GetDelegate<Internal.DataRead.DAQmxReadCounterScalarU32>()(_Session.TaskHandle, timeout, ref readArray, IntPtr.Zero));
        }
        public void ReadCounterScalar(double timeout, ref double readArray)
        {
            _Session.CheckResult(_Session.GetDelegate<Internal.DataRead.DAQmxReadCounterScalarF64>()(_Session.TaskHandle, timeout, ref readArray, IntPtr.Zero));
        }
        public void ReadCtrFreq(int numSampsPerChan, double timeout, bool interleaved, ref double freq, ref double dutyCyle,uint arraySizeInSamps,ref int sampsPerChanRead)
        {
            _Session.CheckResult(_Session.GetDelegate<Internal.DataRead.DAQmxReadCtrFreq>()(_Session.TaskHandle, numSampsPerChan, timeout, interleaved, ref freq, ref dutyCyle, arraySizeInSamps, ref sampsPerChanRead, IntPtr.Zero));
        }
        public void ReadCtrTime(int numSampsPerChan, double timeout, bool interleaved, ref double highTime, ref double lowTime, uint arraySizeInSamps, ref int sampsPerChanRead)
        {
            _Session.CheckResult(_Session.GetDelegate<Internal.DataRead.DAQmxReadCtrTime>()(_Session.TaskHandle, numSampsPerChan, timeout, interleaved, ref highTime, ref lowTime, arraySizeInSamps, ref sampsPerChanRead, IntPtr.Zero));
        }
        public void ReadCtrTicks(int numSampsPerChan, double timeout, bool interleaved, ref uint highTicks, ref uint lowTicks, uint arraySizeInSamps, ref int sampsPerChanRead)
        {
            _Session.CheckResult(_Session.GetDelegate<Internal.DataRead.DAQmxReadCtrTicks>()(_Session.TaskHandle, numSampsPerChan, timeout, interleaved, ref highTicks, ref lowTicks, arraySizeInSamps, ref sampsPerChanRead, IntPtr.Zero));
        }

        public void ReadCtrFreq(double timeout,  ref double freq, ref double dutyCyle)
        {
            _Session.CheckResult(_Session.GetDelegate<Internal.DataRead.DAQmxReadCtrFreqScalar>()(_Session.TaskHandle, timeout, ref freq, ref dutyCyle, IntPtr.Zero));
        }
        public void ReadCtrTime(double timeout, ref double highTime, ref double lowTime)
        {
            _Session.CheckResult(_Session.GetDelegate<Internal.DataRead.DAQmxReadCtrTimeScalar>()(_Session.TaskHandle, timeout, ref highTime, ref lowTime, IntPtr.Zero));
        }
        public void ReadCtrTicks(double timeout, ref uint highTicks, ref uint lowTicks)
        {
            _Session.CheckResult(_Session.GetDelegate<Internal.DataRead.DAQmxReadCtrTicksScalar>()(_Session.TaskHandle, timeout, ref highTicks, ref lowTicks, IntPtr.Zero));
        }
        internal void CreateFreq(string counter, string nameToAssignToChannel, double minVal, double maxVal, CIFreqUnits units, AnalogActiveEdge edge, CIMeasMeth measMethod, double measTime, uint divisor,string customScaleName="")
        {
            _Session.CheckResult(_Session.GetDelegate<Internal.CICreate.DAQmxCreateCIFreqChan>()(_Session.TaskHandle, counter, nameToAssignToChannel, minVal, maxVal, units,edge,measMethod,measTime,divisor, customScaleName));
            if (_Session.Error)
            {
                throw new Exception($"Create Freq Channel fail");
            }
            ChannelName = counter;
        }
        internal void CreatePeriod(string counter,string nameToAssignToChannel, double minVal, double maxVal, CIPeriodUnits units, AnalogActiveEdge edge, CIMeasMeth measMethod, double measTime, uint divisor, string customScaleName="")
        {
            _Session.CheckResult(_Session.GetDelegate<Internal.CICreate.DAQmxCreateCIPeriodChan>()(_Session.TaskHandle, counter, nameToAssignToChannel, minVal, maxVal, units, edge, measMethod, measTime, divisor, customScaleName));
            if (_Session.Error)
            {
                throw new Exception($"Create Period Channel fail");
            }
            ChannelName = counter;
        }
        internal void CreateCountEdges(string counter,string nameToAssignToChannel, AnalogActiveEdge edge= AnalogActiveEdge.Rising, uint initialCount=0, CICountEdgesDir countDirection= CICountEdgesDir.CountDown)
        {
            _Session.CheckResult(_Session.GetDelegate<Internal.CICreate.DAQmxCreateCICountEdgesChan>()(_Session.TaskHandle, counter, nameToAssignToChannel, edge, initialCount, countDirection));
            if (_Session.Error)
            {
                throw new Exception($"Create CountEdges Channel fail");
            }
            ChannelName = counter;
        }
        internal void CreatePulseWidth(string counter,string nameToAssignToChannel, double minVal, double maxVal, CIPeriodUnits units = CIPeriodUnits.Seconds, AnalogActiveEdge startingEdge = AnalogActiveEdge.Rising,string customScaleName="")
        {
            _Session.CheckResult(_Session.GetDelegate<Internal.CICreate.DAQmxCreateCIPulseWidthChan>()(_Session.TaskHandle, counter, nameToAssignToChannel, minVal,maxVal,units,startingEdge,customScaleName));
            if (_Session.Error)
            {
                throw new Exception($"Create PulseWidth Channel fail");
            }
            ChannelName = counter;
        }
        internal void CreateSemiPeriod(string counter, string nameToAssignToChannel, double minVal, double maxVal, CIPeriodUnits units = CIPeriodUnits.Seconds,string customScaleName="")
        {
            _Session.CheckResult(_Session.GetDelegate<Internal.CICreate.DAQmxCreateCISemiPeriodChan>()(_Session.TaskHandle, counter, nameToAssignToChannel, minVal, maxVal, units,customScaleName));
            if (_Session.Error)
            {
                throw new Exception($"Create SemiPeriod Channel fail");
            }
            ChannelName = counter;
        }
        internal void CreateTwoEdgeSep(string counter,string nameToAssignToChannel, double minVal, double maxVal, CIPeriodUnits units, AnalogActiveEdge firstEdge, AnalogActiveEdge secondEdge,string customScaleName="")
        {
            _Session.CheckResult(_Session.GetDelegate<Internal.CICreate.DAQmxCreateCITwoEdgeSepChan>()(_Session.TaskHandle, counter, nameToAssignToChannel, minVal, maxVal, units,firstEdge,secondEdge, customScaleName));
            if (_Session.Error)
            {
                throw new Exception($"Create TwoEdgeSep Channel fail");
            }
            ChannelName = counter;
        }
        internal void CreatePulseFreq(string counter,string nameToAssignToChannel, double minVal, double maxVal, PulseFreqUnits units= PulseFreqUnits.Hz)
        {
            _Session.CheckResult(_Session.GetDelegate<Internal.CICreate.DAQmxCreateCIPulseChanFreq>()(_Session.TaskHandle, counter, nameToAssignToChannel, minVal, maxVal, units));
            if (_Session.Error)
            {
                throw new Exception($"Create PulseFreq Channel fail");
            }
            ChannelName = counter;
        }
        internal void CreatePulseTime(string counter,string nameToAssignToChannel, double minVal, double maxVal, PulseTimeUnits units= PulseTimeUnits.Seconds)
        {
            _Session.CheckResult(_Session.GetDelegate<Internal.CICreate.DAQmxCreateCIPulseChanTime>()(_Session.TaskHandle, counter, nameToAssignToChannel, minVal, maxVal, units));
            if (_Session.Error)
            {
                throw new Exception($"Create PulseTime Channel fail");
            }
            ChannelName = counter;
        }
        internal void CreatePulseTicks(string counter,string nameToAssignToChannel, string sourceTerminal, double minVal, double maxVal)
        {
            _Session.CheckResult(_Session.GetDelegate<Internal.CICreate.DAQmxCreateCIPulseChanTicks>()(_Session.TaskHandle, counter, nameToAssignToChannel,sourceTerminal, minVal, maxVal));
            if (_Session.Error)
            {
                throw new Exception($"Create PulseTicks Channel fail");
            }
            ChannelName = counter;
        }
        internal void CreateLinEncoder(string counter, string nameToAssignToChannel, DecodingType decodingType, bool ZidxEnable, double ZidxVal, CIZIndexPhase ZidxPhase, CILinEncoderUnits units, double distPerPulse, double initialPos, string customScaleName="")
        {
            _Session.CheckResult(_Session.GetDelegate<Internal.CICreate.DAQmxCreateCILinEncoderChan>()(_Session.TaskHandle, counter, nameToAssignToChannel, decodingType,ZidxEnable,ZidxVal,ZidxPhase,units,distPerPulse,initialPos,customScaleName));
            if (_Session.Error)
            {
                throw new Exception($"Create LinEncoder Channel fail");
            }
            ChannelName = counter;
        }
        internal void CreateAngEncoder(string counter,string nameToAssignToChannel, DecodingType decodingType= DecodingType.X1, bool ZidxEnable=false, double ZidxVal=0, CIZIndexPhase ZidxPhase = CIZIndexPhase.AHighBHigh, CIAngEncoderUnits units= CIAngEncoderUnits.Radians, uint pulsesPerRev=24, double initialAngle=0,string customScaleName="")
        {
            _Session.CheckResult(_Session.GetDelegate<Internal.CICreate.DAQmxCreateCIAngEncoderChan>()(_Session.TaskHandle, counter, nameToAssignToChannel, decodingType, ZidxEnable, ZidxVal, ZidxPhase, units, pulsesPerRev, initialAngle, customScaleName));
            if (_Session.Error)
            {
                throw new Exception($"Create AngEncoder Channel fail");
            }
            ChannelName = counter;
        }
        internal void CreateLinVelocity(string counter,string nameToAssignToChannel, double minVal, double maxVal, DecodingType decodingType, VelocityUnits units, double distPerPulse, string customScaleName="")
        {
            _Session.CheckResult(_Session.GetDelegate<Internal.CICreate.DAQmxCreateCILinVelocityChan>()(_Session.TaskHandle, counter, nameToAssignToChannel,minVal,maxVal, decodingType, units, distPerPulse, customScaleName));
            if (_Session.Error)
            {
                throw new Exception($"Create LinVelocity Channel fail");
            }
            ChannelName = counter;
        }
        internal void CreateAngVelocity(string counter,string nameToAssignToChannel, double minVal, double maxVal, DecodingType decodingType, VelocityAngEncoderUnits units, uint pulsesPerRev,string customScaleName="")
        {
            _Session.CheckResult(_Session.GetDelegate<Internal.CICreate.DAQmxCreateCIAngVelocityChan>()(_Session.TaskHandle, counter, nameToAssignToChannel, minVal, maxVal, decodingType, units, pulsesPerRev, customScaleName));
            if (_Session.Error)
            {
                throw new Exception($"Create AngVelocity Channel fail");
            }
            ChannelName = counter;
        }
        internal void CreateGPSTimestamp(string counter,string nameToAssignToChannel, TimestampUnits units = TimestampUnits.Seconds, GPSSyncMethod syncMethod = GPSSyncMethod.IRIGB, string customScaleName="")
        {
            _Session.CheckResult(_Session.GetDelegate<Internal.CICreate.DAQmxCreateCIGPSTimestampChan>()(_Session.TaskHandle, counter, nameToAssignToChannel, units, syncMethod, customScaleName));
            if (_Session.Error)
            {
                throw new Exception($"Create GPSTimestamp Channel fail");
            }
            ChannelName = counter;
        }
    }
}
