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

namespace NIDAQmx
{
    public class Product : BaseDevice
    {
        internal Product(DAQmxSession session, string deviceName) : base(session, deviceName)
        {
            Accessory = new Accessory(session, deviceName);
            FieldDAQ = new FieldDAQ(session, deviceName);
            ProductCategory = GetProductCategory();
            ProductType = GetProductType();
            ProductNum =GetProductNum();
            SerialNum = GetSerialNum();
            CarrierSerialNum = GetCarrierSerialNum();
        }
        private ProductCategory GetProductCategory()
        {
            ProductCategory category = ProductCategory.AOSeries;
            _Session.CheckResult(_Session.GetDelegate<Internal.Internal.DAQmxGetDevProductCategory>()(DeviceName, ref category));
            return category;
        }
        private string GetProductType()
        {
            byte[] bytes = new byte[1024];
            _Session.CheckResult(_Session.GetDelegate<Internal.Internal.DAQmxGetDevProductType>()(DeviceName, ref bytes[0], (uint)bytes.Length));
            return Encoding.UTF8.GetString(bytes).Trim('\0');
        }
        private uint GetProductNum()
        {
            uint val = 0;
            _Session.CheckResult(_Session.GetDelegate<Internal.Internal.DAQmxGetDevProductNum>()(DeviceName,ref val));
            return val;
        }
        private uint GetSerialNum()
        {
            uint val = 0;
            _Session.CheckResult(_Session.GetDelegate<Internal.Internal.DAQmxGetDevSerialNum>()(DeviceName, ref val));
            return val;
        }
        private uint GetCarrierSerialNum()
        {
            uint val = 0;
            _Session.CheckResult(_Session.GetDelegate<Internal.Internal.DAQmxGetCarrierSerialNum>()(DeviceName, ref val));
            return val;
        }
        public ProductCategory ProductCategory { get; }
        public string ProductType { get; }
        public uint ProductNum { get; }
        public uint SerialNum { get; }
        public Accessory Accessory { get; }
        public FieldDAQ FieldDAQ { get; }
        public uint CarrierSerialNum { get; }
    }
    public class Accessory : BaseDevice
    {
        internal Accessory(DAQmxSession session, string deviceName) : base(session, deviceName)
        {
            ProductTypes = GetProductTypes();
            ProductNums = GetProductNums();
            SerialNums = GetSerialNums() ;
        }

        private string[] GetProductTypes()
        {
            byte[] bytes = new byte[1024];
            _Session.CheckResult(_Session.GetDelegate<Internal.Internal.DAQmxGetDevAccessoryProductTypes>()(DeviceName, ref bytes[0], (uint)bytes.Length));
            return Encoding.UTF8.GetString(bytes).Trim('\0').Split(',').Select(x=>x.Trim('\0')).Where(x=>!string.IsNullOrEmpty(x)).ToArray();
        }
        private uint[] GetProductNums()
        {
            uint[] val = new uint[1024];
            _Session.CheckResult(_Session.GetDelegate<Internal.Internal.DAQmxGetDevAccessoryProductNums>()(DeviceName, ref val[0],(uint)val.Length));
            return val.Where(x => x != 0).ToArray();
        }
        private uint[] GetSerialNums()
        {
            uint[] val = new uint[1024];
            _Session.CheckResult(_Session.GetDelegate<Internal.Internal.DAQmxGetDevAccessorySerialNums>()(DeviceName, ref val[0], (uint)val.Length));
            return val.Where(x => x != 0).ToArray();
        }
        public string[] ProductTypes { get; }
        public uint[] ProductNums { get; }
        public uint[] SerialNums { get; }
    }
    public class FieldDAQ : BaseDevice
    {
        internal FieldDAQ(DAQmxSession session, string deviceName) : base(session, deviceName)
        {
            DevName = GetDevName();
            BankDevNames = GetBankDevNames();
        }
        private string GetDevName()
        {
            byte[] bytes = new byte[1024];
            _Session.CheckResult(_Session.GetDelegate<Internal.Internal.DAQmxGetFieldDAQDevName>()(DeviceName, ref bytes[0], (uint)bytes.Length));
            return Encoding.UTF8.GetString(bytes).Trim('\0');
        }
        private string[] GetBankDevNames()
        {
            byte[] bytes = new byte[1024];
            _Session.CheckResult(_Session.GetDelegate<Internal.Internal.DAQmxGetFieldDAQBankDevNames>()(DeviceName, ref bytes[0], (uint)bytes.Length));
            return Encoding.UTF8.GetString(bytes).Trim('\0').Split(',').Select(x => x.Trim('\0')).Where(x => !string.IsNullOrEmpty(x)).ToArray();
        }
        public string DevName { get; }
        public string[] BankDevNames { get; }
    }
}
