using Microsoft.VisualBasic;
using NIDAQmx.DAQmxEnum;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
using System.Reflection;

namespace NIDAQmx
{
    public abstract class ChannelFactory
    {
        private DAQmx _DAQmx;
        internal ChannelFactory(DAQmx daqmx)
        {
            _DAQmx = daqmx;
        }
        private protected T Exc<T>(Expression<Func<T, Delegate>> expr, params object[] vals) where T:Channel
        {
            if (expr.Body is UnaryExpression)
            {
                var lastnames = _DAQmx.Task.Channels;
                var channel = (T)typeof(T).GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault().Invoke(new object[] { _DAQmx.Session });
                MethodInfo methodInfo = (MethodInfo)((((UnaryExpression)expr.Body).Operand as dynamic).Object.Value);
                var para = methodInfo.GetParameters();
                if(para.Length!=vals.Length)
                {
                    throw new ArgumentException("args count error");
                }
                for(int i=0;i<vals.Length;i++)
                {
                    if (para[i].ParameterType != vals[i].GetType())
                    {
                        throw new ArgumentException($"{i + 1} parameter type error");
                    }
                }
                methodInfo.Invoke(channel, vals);
                _DAQmx.AddChannel(channel);
                var newnames = _DAQmx.Task.Channels;
                foreach (var val in newnames.Except(lastnames))
                {
                    channel.Configs.Add(new ChannelConfig(_DAQmx.Session)
                    {
                        ActiveChans = val,
                    });
                }
                return channel;
            }
            throw new Exception();
        }
    }
}
