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

namespace NIDAQmx
{
    public class AOChannelConfig : BaseChannelConfig
    {
        internal AOChannelConfig(ChannelAttributeSession session) : base(session)
        {
            AttributeSession = session;
            Voltage = new VoltageConfig(session);
            Current = new CurrentConfig(session);
            FuncGen = new FuncGenConfig(session);
            GeneralProperties = new GeneralPropertiesConfig(session);
        }
        [AllowNull]
        internal override ChannelAttributeSession AttributeSession { get; }
        public double Max { get => AttributeSession.GetValue<Internal.AO.DAQmxGetAOMax,double>(); set => AttributeSession.SetValue<Internal.AO.DAQmxSetAOMax,double>(value); }
        public double Min { get => AttributeSession.GetValue<Internal.AO.DAQmxGetAOMin,double>(); set => AttributeSession.SetValue<Internal.AO.DAQmxSetAOMin,double>(value); }
        public string CustomScaleName { get => AttributeSession.GetValue<Internal.AO.DAQmxGetAOCustomScaleName>(); set => AttributeSession.SetValue<Internal.AO.DAQmxSetAOCustomScaleName>(value); }
        public AOSupportedOutputTypes OutputType
        {
            get
            {
                AOSupportedOutputTypes types = AOSupportedOutputTypes.Voltage;
                _DAQmxSession.CheckResult(_DAQmxSession.GetDelegate<Internal.AO.DAQmxGetAOOutputType>()(_DAQmxSession.TaskHandle, AttributeSession.ActiveChans, ref types));
                return types;
            }
        }
        public VoltageConfig Voltage { get; }
        public CurrentConfig Current { get; }
        public FuncGenConfig FuncGen { get; }
        public GeneralPropertiesConfig GeneralProperties { get; }
        public class VoltageConfig
        {
            ChannelAttributeSession _Session;
            internal VoltageConfig(ChannelAttributeSession session)
            {
                _Session = session;
            }
            public AOVoltageUnits Units { get => _Session.GetValue<Internal.AO.DAQmxGetAOVoltageUnits,AOVoltageUnits>(); set => _Session.SetValue<Internal.AO.DAQmxSetAOVoltageUnits,AOVoltageUnits>(value); }
            public double CurrentLimit { get => _Session.GetValue<Internal.AO.DAQmxGetAOVoltageCurrentLimit,double>(); set => _Session.SetValue<Internal.AO.DAQmxSetAOVoltageCurrentLimit,double>(value); }
        }

        public class CurrentConfig
        {
            ChannelAttributeSession _Session;
            internal CurrentConfig(ChannelAttributeSession session)
            {
                _Session = session;
            }
            public AnalogCurrentUnit Unit { get => _Session.GetValue<Internal.AO.DAQmxGetAOCurrentUnits,AnalogCurrentUnit>(); set => _Session.SetValue<Internal.AO.DAQmxSetAOCurrentUnits,AnalogCurrentUnit>(value); }
        }

        public class FuncGenConfig
        {
            ChannelAttributeSession _Session;
            internal FuncGenConfig(ChannelAttributeSession session)
            {
                _Session = session;
            }
            public AOFuncGenType Type { get => _Session.GetValue<Internal.AO.DAQmxGetAOFuncGenType,AOFuncGenType>(); set => _Session.SetValue<Internal.AO.DAQmxSetAOFuncGenType,AOFuncGenType>(value); }
            public double Freq { get => _Session.GetValue<Internal.AO.DAQmxGetAOFuncGenFreq,double>(); set => _Session.SetValue<Internal.AO.DAQmxSetAOFuncGenFreq,double>(value); }
            public double Amplitude { get => _Session.GetValue<Internal.AO.DAQmxGetAOFuncGenAmplitude,double>(); set => _Session.SetValue<Internal.AO.DAQmxSetAOFuncGenAmplitude,double>(value); }
            public double Offset { get => _Session.GetValue<Internal.AO.DAQmxGetAOFuncGenOffset,double>(); set => _Session.SetValue<Internal.AO.DAQmxSetAOFuncGenOffset,double>(value); }
            public double SquareDutyCycle { get => _Session.GetValue<Internal.AO.DAQmxGetAOFuncGenSquareDutyCycle,double>(); set => _Session.SetValue<Internal.AO.DAQmxSetAOFuncGenSquareDutyCycle,double>(value); }
            public double FMDeviation { get => _Session.GetValue<Internal.AO.DAQmxGetAOFuncGenFMDeviation,double>(); set => _Session.SetValue<Internal.AO.DAQmxSetAOFuncGenFMDeviation,double>(value); }
            public AOFuncGenModulationType ModulationType { get => _Session.GetValue<Internal.AO.DAQmxGetAOFuncGenModulationType,AOFuncGenModulationType>(); set => _Session.SetValue<Internal.AO.DAQmxSetAOFuncGenModulationType,AOFuncGenModulationType>(value); }
        }
        public class GeneralPropertiesConfig
        {
            ChannelAttributeSession _Session;
            internal GeneralPropertiesConfig(ChannelAttributeSession session)
            {
                _Session = session;
                Advanced = new AdvancedConfig(session);
            }
            public AdvancedConfig Advanced { get; }
            public double LoadImpedance { get => _Session.GetValue<Internal.AO.DAQmxGetAOLoadImpedance,double>(); set => _Session.SetValue<Internal.AO.DAQmxSetAOLoadImpedance,double>(value); }
            public AOIdleOutputBehavior IdleOutputBehavior { get => _Session.GetValue<Internal.AO.DAQmxGetAOIdleOutputBehavior,AOIdleOutputBehavior>(); set => _Session.SetValue<Internal.AO.DAQmxSetAOIdleOutputBehavior, AOIdleOutputBehavior>(value); }
            public double OutputImpedance { get => _Session.GetValue<Internal.AO.DAQmxGetAOOutputImpedance,double>(); set => _Session.SetValue<Internal.AO.DAQmxSetAOOutputImpedance,double>(value); }
            public TerminalConfig TerminalConfig { get => _Session.GetValue<Internal.AO.DAQmxGetAOTermCfg,TerminalConfig>(); set => _Session.SetValue<Internal.AO.DAQmxSetAOTermCfg,TerminalConfig>(value); }

            public double FilterDelay { get => _Session.GetValue<Internal.AO.DAQmxGetAOFilterDelay,double>(); set => _Session.SetValue<Internal.AO.DAQmxSetAOFilterDelay,double>(value); }
            public double FilterDelayAdjustment { get => _Session.GetValue<Internal.AO.DAQmxGetAOFilterDelayAdjustment,double>(); set => _Session.SetValue<Internal.AO.DAQmxSetAOFilterDelayAdjustment,double>(value); }
            public FilterDelayUnits DelayUnits { get => _Session.GetValue<Internal.AO.DAQmxGetAOFilterDelayUnits,FilterDelayUnits>(); set => _Session.SetValue<Internal.AO.DAQmxSetAOFilterDelayUnits,FilterDelayUnits>(value); }
            public class DACConfig
            {
                ChannelAttributeSession _Session;
                internal DACConfig(ChannelAttributeSession session)
                {
                    _Session = session;
                }
                public bool ReglitchEnable { get => _Session.GetValue<Internal.AO.DAQmxGetAOReglitchEnable,bool>(); set => _Session.SetValue<Internal.AO.DAQmxSetAOReglitchEnable,bool>(value); }
                public ResolutionUnits ResolutionUnits { get => _Session.GetValue<Internal.AO.DAQmxGetAOResolutionUnits,ResolutionUnits>(); set => _Session.SetValue<Internal.AO.DAQmxSetAOResolutionUnits,ResolutionUnits>(value); }
                public double Resolution => _Session.GetValue<Internal.AO.DAQmxGetAOResolution,double>();
                public double RangeHigh { get => _Session.GetValue<Internal.AO.DAQmxGetAODACRngHigh,double>(); set => _Session.SetValue<Internal.AO.DAQmxSetAODACRngHigh,double>(value); }
                public double RangeLow { get => _Session.GetValue<Internal.AO.DAQmxGetAODACRngLow,double>(); set => _Session.SetValue<Internal.AO.DAQmxSetAODACRngLow,double>(value); }
                public bool RefConnToGnd { get => _Session.GetValue<Internal.AO.DAQmxGetAODACRefConnToGnd,bool>(); set => _Session.SetValue<Internal.AO.DAQmxSetAODACRefConnToGnd,bool>(value); }
                public bool RefAllowConnToGnd { get => _Session.GetValue<Internal.AO.DAQmxGetAODACRefAllowConnToGnd,bool>(); set => _Session.SetValue<Internal.AO.DAQmxSetAODACRefAllowConnToGnd,bool>(value); }
                public ClkSrc RefSrc { get => _Session.GetValue<Internal.AO.DAQmxGetAODACRefSrc,ClkSrc>(); set => _Session.SetValue<Internal.AO.DAQmxSetAODACRefSrc,ClkSrc>(value); }
                public string RefExtSrc { get => _Session.GetValue<Internal.AO.DAQmxGetAODACRefExtSrc>(); set => _Session.SetValue<Internal.AO.DAQmxSetAODACRefExtSrc>(value); }
                public double RefVal { get => _Session.GetValue<Internal.AO.DAQmxGetAODACRefVal,double>(); set => _Session.SetValue<Internal.AO.DAQmxSetAODACRefVal,double>(value); }

                public ClkSrc OffsetSrc { get => _Session.GetValue<Internal.AO.DAQmxGetAODACOffsetSrc,ClkSrc>(); set => _Session.SetValue<Internal.AO.DAQmxSetAODACOffsetSrc,ClkSrc>(value); }
                public string OffsetExtSrc { get => _Session.GetValue<Internal.AO.DAQmxGetAODACOffsetExtSrc>(); set => _Session.SetValue<Internal.AO.DAQmxSetAODACOffsetExtSrc>(value); }
                public double OffsetVal { get => _Session.GetValue<Internal.AO.DAQmxGetAODACOffsetVal,double>(); set => _Session.SetValue<Internal.AO.DAQmxSetAODACOffsetVal,double>(value); }

            }
        }

        public class AdvancedConfig
        {
            ChannelAttributeSession _Session;
            internal AdvancedConfig(ChannelAttributeSession session)
            {
                _Session = session;
            }
            public double Gain { get => _Session.GetValue<Internal.AO.DAQmxGetAOGain,double>(); set => _Session.SetValue<Internal.AO.DAQmxSetAOGain,double>(value); }
            public bool UseOnlyOnBrdMem { get => _Session.GetValue<Internal.AO.DAQmxGetAOUseOnlyOnBrdMem,bool>(); set => _Session.SetValue<Internal.AO.DAQmxSetAOUseOnlyOnBrdMem,bool>(value); }
            public DataXferMech DataXferMech { get => _Session.GetValue<Internal.AO.DAQmxGetAODataXferMech,DataXferMech>(); set => _Session.SetValue<Internal.AO.DAQmxSetAODataXferMech,DataXferMech>(value); }
            public OutDataXferReqCond DataXferReqCond { get => _Session.GetValue<Internal.AO.DAQmxSetAODataXferReqCond,OutDataXferReqCond>(); set => _Session.SetValue<Internal.AO.DAQmxSetAODataXferReqCond,OutDataXferReqCond>(value); }
            public uint UsbXferReqSize { get => _Session.GetValue<Internal.AO.DAQmxGetAOUsbXferReqSize,uint>(); set => _Session.SetValue<Internal.AO.DAQmxSetAOUsbXferReqSize,uint>(value); }
            public uint UsbXferReqCount { get => _Session.GetValue<Internal.AO.DAQmxGetAOUsbXferReqCount,uint>(); set => _Session.SetValue<Internal.AO.DAQmxSetAOUsbXferReqCount,uint>(value); }
            public bool MemMapEnable { get => _Session.GetValue<Internal.AO.DAQmxGetAOMemMapEnable,bool>(); set => _Session.SetValue<Internal.AO.DAQmxSetAOMemMapEnable,bool>(value); }
            public double[] DevScalingCoeff
            {
                get
                {
                    double[] result = new double[100];
                    _Session.Session.CheckResult(_Session.Session.GetDelegate<Internal.AO.DAQmxGetAODevScalingCoeff>()(_Session.Session.TaskHandle, _Session.ActiveChans, ref result[0], (uint)result.Length));
                    return result.Where(x=>x!=0).ToArray();
                }
            }
            public bool EnhancedImageRejectionEnable { get => _Session.GetValue<Internal.AO.DAQmxGetAOEnhancedImageRejectionEnable,bool>(); set => _Session.SetValue<Internal.AO.DAQmxSetAOEnhancedImageRejectionEnable,bool>(value); }

        }
    }
}
