using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace NIFPGA
{
    public class Irq
    {
        private FPGASession _Session;
        private IntPtr _Handle = IntPtr.Zero;
        internal Irq(FPGASession session)
        {
            _Session = session;
        }
        public void Reserve()
        {
            if (_Handle != IntPtr.Zero) return;
            _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_ReserveIrqContext>()(_Session.Session, ref _Handle));
        }
        public IrqResult WaitOnIrqs(NiFpga_Irq irq,uint timeout)
        {
            if(_Handle == IntPtr.Zero)
            {
                throw new Exception($"Need Call {nameof(Reserve)}");
            }
            IrqResult result = new IrqResult(timeout, irq);
            _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_WaitOnIrqs>()(_Session.Session, _Handle, irq, timeout, ref result.IrqsAsserted, ref result.IsTimeOut));
            return result;
        }
        public void WaitOnIrqs(ref IrqResult result)
        {
            if (_Handle == IntPtr.Zero)
            {
                throw new Exception($"Need Call {nameof(Reserve)}");
            }
            _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_WaitOnIrqs>()(_Session.Session, _Handle, result.Irqs, result.TimeOut, ref result.IrqsAsserted, ref result.IsTimeOut));
            result.IsAcknowledge = false;
        }
        public void AcknowledgeIrqs(ref IrqResult result)
        {
            if (result.IsAcknowledge) return;
            _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_AcknowledgeIrqs>()(_Session.Session, result.Irqs));
            result.IsAcknowledge = true;
        }
        public void Unreserve()
        {
            if (_Handle != IntPtr.Zero) return;
            _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_UnreserveIrqContext>()(_Session.Session, _Handle));
            _Handle = IntPtr.Zero;
        }
    }
    public struct IrqResult
    {
        public IrqResult(uint timeOut, NiFpga_Irq irqs)
        {
            TimeOut = timeOut;
            Irqs = irqs;
        }

        public uint TimeOut;
        public Boolean IsTimeOut;
        public uint IrqsAsserted;
        public NiFpga_Irq Irqs;
        public bool IsAcknowledge;
    }
}
