using System.Collections.Concurrent;
using System.Runtime.InteropServices;
using System.Text;

namespace NIFPGA
{
    internal sealed class FPGASession
    {
        private readonly string windowsdllname = "NiFpga";
        private readonly string linuxdllname = "libNiFpga.so";
        private NativeLibraryLoader.NativeLoader _NativeLoader;
        public Boolean Error { get; private set; } = false;
        public String Message { get; private set; } = string.Empty;
        private uint session;
        public uint Session => session;
        internal FPGASession()
        {
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) _NativeLoader = new NativeLibraryLoader.NativeLoader(windowsdllname);
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                _NativeLoader = new NativeLibraryLoader.NativeLoader(linuxdllname);
                _NativeLoader.SearchDirectories.Add("/usr/lib/x86_64-linux-gnu/");
            }
            else
            {
                throw new PlatformNotSupportedException();
            }
            _NativeLoader.Init();
        }
        public void Close()
        {
            CheckResult(GetDelegate<Interop.NiFpgaDll_Close>()(session, Interop.NiFpga_CloseAttribute.NiFpga_CloseAttribute_NoResetIfLastSession));
            session = 0;
        }

        public void Open(string bitfile,string signature,string resource,NiFpga_OpenAttribute attribute)
        {
            CheckResult(GetDelegate<Interop.NiFpgaDll_Open>()(bitfile, signature, resource, attribute, ref session));
        }
        public T GetDelegate<T>() where T : Delegate
        {
            return _NativeLoader.LoadFunction<T>(typeof(T).Name);
        }
        public void CheckResult(NiFpga_Status result)
        {
            Error = result < NiFpga_Status.Success;
            Message = result.ToString();
        }
    }
}
