using NativeLibraryLoader;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http.Headers;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace NIFPGA
{
    public abstract class FPGABase
    {
        protected private FPGASession _Session;
        internal FPGABase(FPGASession session) 
        {
            _Session = session;
        }
    }
    public abstract class Fifo : FPGABase
    {
        private NiFpga_HostBufferType _HostBufferType;
        private uint _BytesPerElement;
        internal Fifo(FPGASession session,uint fifosession) : base(session)
        {
            FifoSession= fifosession;
            if (_Session.Session == 0) return;
            int value = 0;
            _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_GetFifoPropertyI32>()(_Session.Session, fifosession, Interop.NiFpga_FifoProperty.NiFpga_FifoProperty_HostBufferType, ref value));
            _HostBufferType = (NiFpga_HostBufferType)value;
            _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_GetFifoPropertyU32>()(_Session.Session, fifosession, Interop.NiFpga_FifoProperty.NiFpga_FifoProperty_BytesPerElement, ref _BytesPerElement));
        }
        public string Name { get; init; } = string.Empty;
        private uint GetHostBufferAllocationGranularity()
        {
            uint value = 0;
            _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_GetFifoPropertyU32>()(_Session.Session, FifoSession, Interop.NiFpga_FifoProperty.NiFpga_FifoProperty_HostBufferAllocationGranularity, ref value));
            return value;
        }
        private void SetHostBufferAllocationGranularity(uint value)
        {
            _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_SetFifoPropertyU32>()(_Session.Session, FifoSession, Interop.NiFpga_FifoProperty.NiFpga_FifoProperty_HostBufferAllocationGranularity, value));
        }
        public uint HostBufferAllocationGranularity
        {
            get=>GetHostBufferAllocationGranularity();set=>SetHostBufferAllocationGranularity(value);
        }
        private ulong GetHostBufferSize()
        {
            ulong value = 0;
            _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_GetFifoPropertyU64>()(_Session.Session, FifoSession, Interop.NiFpga_FifoProperty.NiFpga_FifoProperty_HostBufferSize, ref value));
            return value;
        }
        private void SetHostBufferSize(ulong value)
        {
            _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_SetFifoPropertyU64>()(_Session.Session, FifoSession, Interop.NiFpga_FifoProperty.NiFpga_FifoProperty_HostBufferSize, value));
        }
        private ulong GetHostBufferMirrorSize()
        {
            ulong value = 0;
            _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_GetFifoPropertyU64>()(_Session.Session, FifoSession, Interop.NiFpga_FifoProperty.NiFpga_FifoProperty_HostBufferMirrorSize, ref value));
            return value;
        }
        private void SetHostBufferMirrorSize(ulong value)
        {
            _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_SetFifoPropertyU64>()(_Session.Session, FifoSession, Interop.NiFpga_FifoProperty.NiFpga_FifoProperty_HostBufferMirrorSize, value));
        }
        public ulong HostBufferSize { get => GetHostBufferSize(); set => SetHostBufferSize(value); }
        public ulong HostBufferMirrorSize { get=>GetHostBufferMirrorSize(); set=>SetHostBufferMirrorSize(value); }
        public UInt32 FifoSession { get; }
        public NiFpga_FifoFlowControl FifoFlowControl { get=>GetFlowControl(); set=>SetFlowControl(value); }
        public NiFpga_HostBufferType HostBufferType => _HostBufferType;
        public uint BytesPerElement => _BytesPerElement;

        private NiFpga_FifoFlowControl GetFlowControl()
        {
            int value = 0;
            _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_GetFifoPropertyI32>()(_Session.Session, FifoSession, Interop.NiFpga_FifoProperty.NiFpga_FifoProperty_FlowControl, ref value));
            return (NiFpga_FifoFlowControl)value;
        }
        private void SetFlowControl(NiFpga_FifoFlowControl flowControl)
        {
            _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_SetFifoPropertyI32>()(_Session.Session, FifoSession, Interop.NiFpga_FifoProperty.NiFpga_FifoProperty_FlowControl, (int)flowControl));
        }
        public void Start()
        {
            _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_StartFifo>()(_Session.Session, FifoSession));
        }
        public void Stop()
        {
            _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_StopFifo>()(_Session.Session, FifoSession));
        }
        public void Unreserve()
        {
            _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_UnreserveFifo>()(_Session.Session, FifoSession));
        }
        public void CommitConfiguration()
        {
            _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_CommitFifoConfiguration>()(_Session.Session, FifoSession));
        }
        public override string ToString()
        {
            return Name;
        }
    }
}
