using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;

namespace LMS_Demo
{
    public static class LMSWrapper
    {
        static UInt32[] MyDevArray = new UInt32[64]; 

        //  .......... The dll imports ..........
        /// <summary>
        /// For the function declarations the C# bool type is explicitly converted to the int type used in the C++ environment
        /// While the actual .net local variable and argument passing version of a bool is actually 4 bytes, it is safer to make
        /// the conversion explicitly.
        /// </summary>
        /// <returns></returns>


 

        // ... some simple wrapper functions ...

        public static int GetNumberOfDevices()
        {
            return NativeMethods.fnLMS_GetNumDevices();
        }

        public static void SetTestMode(bool mode)
        {
            int i;
            if (mode) i = 1;
            else i = 0;

            NativeMethods.fnLMS_SetTestMode(i);
        }

        public static int GetDevInfo()
        {
            int tmp;
            tmp = NativeMethods.fnLMS_GetDevInfo(MyDevArray);

            return tmp;
        }

        public static int GetSerialNumber(UInt32 Device)
        {
            return NativeMethods.fnLMS_GetSerialNumber(MyDevArray[Device]);
        }

        public static int InitDevice(UInt32 Device)
        {
            return NativeMethods.fnLMS_InitDevice(MyDevArray[Device]);
        }

        public static int CloseDevice(UInt32 Device)
        {
            return NativeMethods.fnLMS_CloseDevice(MyDevArray[Device]);
        }

        // --- GetModelName marshalls the char string into a C# style string object ---
        public static string GetModelName(UInt32 Device)
        {
            int status;
            byte[] pModelName = new byte[32];
            status = NativeMethods.fnLMS_GetModelName(MyDevArray[Device], pModelName);

            string ModelName = Encoding.ASCII.GetString(pModelName).TrimEnd(new char[] { '\0' });
            return ModelName;

        }

        public static int GetDLLVersion()
        {
            return NativeMethods.fnLMS_GetDLLVersion();
        }

        public static int GetDeviceStatus(UInt32 Device)
        {
            return NativeMethods.fnLMS_GetDeviceStatus(MyDevArray[Device]);
        }

        public static int SetFrequency(UInt32 Device, int frequency)
        {
           return NativeMethods.fnLMS_SetFrequency(MyDevArray[Device], frequency);
        }

        public static int SetStartFrequency(UInt32 Device, int startfrequency)
        {
            return NativeMethods.fnLMS_SetStartFrequency(MyDevArray[Device], startfrequency);
        }

        public static int SetEndFrequency(UInt32 Device, int endfrequency)
        {
           return NativeMethods.fnLMS_SetEndFrequency(MyDevArray[Device], endfrequency);
        }

        public static int SetSweepTime(UInt32 Device, int sweeptime)
        {
            return NativeMethods.fnLMS_SetSweepTime(MyDevArray[Device], sweeptime);
        }

        public static int SetPowerLevel(UInt32 Device, int powerlevel)
        {
            return NativeMethods.fnLMS_SetPowerLevel(MyDevArray[Device], powerlevel);
        }

        public static int SetRFOn(UInt32 Device, bool on)
        {
            // we'll do an explicit conversion to avoid any future platform specific issues
            int i;
            if (on) i = 1;
            else i = 0;

            return NativeMethods.fnLMS_SetRFOn(MyDevArray[Device], i);
        }

        public static int SetPulseOnTime(UInt32 Device, float pulseontime)
        {
            return NativeMethods.fnLMS_SetPulseOnTime(MyDevArray[Device], pulseontime);
        }

        public static int SetPulseOffTime(UInt32 Device, float pulseofftime)
        {
            return NativeMethods.fnLMS_SetPulseOffTime(MyDevArray[Device], pulseofftime);
        }

        public static int fnLMS_EnableInternalPulseMod(UInt32 Device, bool on)
        {
            // we'll do an explicit conversion to avoid any future platform specific issues
            int i;
            if (on) i = 1;
            else i = 0;

            return NativeMethods.fnLMS_EnableInternalPulseMod(MyDevArray[Device], i);
        }

        public static int SetUseExternalPulseMod(UInt32 Device, bool external)
        {
            // we'll do an explicit conversion to avoid any future platform specific issues
            int i;
            if (external) i = 1;
            else i = 0;

            return NativeMethods.fnLMS_SetUseExternalPulseMod(MyDevArray[Device], i);
        }

        public static int SetFastPulsedOutput(UInt32 Device, float pulseontime, float pulsereptime, bool on)
        {
            // we'll do an explicit conversion to avoid any future platform specific issues
            int i;
            if (on) i = 1;
            else i = 0;

            return NativeMethods.fnLMS_SetFastPulsedOutput(MyDevArray[Device], pulseontime, pulsereptime, i);
        }

        public static int SetUseInternalRef(UInt32 Device, bool src_internal)
        {            
            // we'll do an explicit conversion to avoid any future platform specific issues
            int i;
            if (src_internal) i = 1;
            else i = 0;

            return NativeMethods.fnLMS_SetUseInternalRef(MyDevArray[Device], i);
        }

        public static int SetSweepDirection(UInt32 Device, bool up)
        {
            // we'll do an explicit conversion to avoid any future platform specific issues
            int i;
            if (up) i = 1;
            else i = 0;

            return NativeMethods.fnLMS_SetSweepDirection(MyDevArray[Device], i);
        }

        public static int fnLMS_SetSweepMode(UInt32 Device, bool mode)
        {
            // we'll do an explicit conversion to avoid any future platform specific issues
            int i;
            if (mode) i = 1;
            else i = 0;

            return NativeMethods.fnLMS_SetSweepMode(MyDevArray[Device], i);
        }

        public static int SetSweepType(UInt32 Device, bool swptype)
        {
            // we'll do an explicit conversion to avoid any future platform specific issues
            int i;
            if (swptype) i = 1;
            else i = 0;

            return NativeMethods.fnLMS_SetSweepType(MyDevArray[Device], i);
        }

        public static int StartSweep(UInt32 Device, bool go)
        {
            // we'll do an explicit conversion to avoid any future platform specific issues
            int i;
            if (go) i = 1;
            else i = 0;

            return NativeMethods.fnLMS_StartSweep(MyDevArray[Device], i);
        }

        public static int SaveSettings(UInt32 Device)
        {
            return NativeMethods.fnLMS_SaveSettings(MyDevArray[Device]);
        }


        // -- methods to return values --

        public static int GetFrequency(UInt32 Device)
        {
            return NativeMethods.fnLMS_GetFrequency(MyDevArray[Device]);
        }

        public static int GetStartFrequency(UInt32 Device)
        {
            return NativeMethods.fnLMS_GetStartFrequency(MyDevArray[Device]);
        }

        public static int GetEndFrequency(UInt32 Device)
        {
            return NativeMethods.fnLMS_GetEndFrequency(MyDevArray[Device]);
        }

        public static int GetSweepTime(UInt32 Device)
        {
            return NativeMethods.fnLMS_GetSweepTime(MyDevArray[Device]);
        }

        public static int GetUseInternalRef(UInt32 Device)
        {
            return NativeMethods.fnLMS_GetUseInternalRef(MyDevArray[Device]);
        }

        public static int GetPowerLevel(UInt32 Device)
        {
            return NativeMethods.fnLMS_GetPowerLevel(MyDevArray[Device]);
        }

        public static int GetAbsPowerLevel(UInt32 Device)
        {
            return NativeMethods.fnLMS_GetAbsPowerLevel(MyDevArray[Device]);
        }

        public static int GetMaxPwr(UInt32 Device)
        {
            return NativeMethods.fnLMS_GetMaxPwr(MyDevArray[Device]);
        }

        public static int GetMinPwr(UInt32 Device)
        {
            return NativeMethods.fnLMS_GetMinPwr(MyDevArray[Device]);
        }

        public static int GetRF_On(UInt32 Device)
        {
            return NativeMethods.fnLMS_GetRF_On(MyDevArray[Device]);
        }

        public static int GetMaxFreq(UInt32 Device)
        {
            return NativeMethods.fnLMS_GetMaxFreq(MyDevArray[Device]);
        }

        public static int GetMinFreq(UInt32 Device)
        {
            return NativeMethods.fnLMS_GetMinFreq(MyDevArray[Device]);
        }

        public static int GetPulseOnTime(UInt32 Device)
        {
            return NativeMethods.fnLMS_GetPulseOnTime(MyDevArray[Device]);
        }

        public static int GetPulseOffTime(UInt32 Device)
        {
            return NativeMethods.fnLMS_GetPulseOffTime(MyDevArray[Device]);
        }

        public static int GetPulseMode(UInt32 Device)
        {
            return NativeMethods.fnLMS_GetPulseMode(MyDevArray[Device]);
        }

        public static int GetHasFastPulseMode(UInt32 Device)
        {
            return NativeMethods.fnLMS_GetHasFastPulseMode(MyDevArray[Device]);
        }

        public static int GetUseInternalPulseMod(UInt32 Device)
        {
            return NativeMethods.fnLMS_GetUseInternalPulseMod(MyDevArray[Device]);
        }

    }

    internal static class NativeMethods
    {
        //  .......... The dll imports ..........
        /// <summary>
        /// For the function declarations the C# bool type is explicitly converted to the int type used in the C++ environment
        /// While the actual .net local variable and argument passing version of a bool is actually 4 bytes, it is safer to make
        /// the conversion explicitly.
        /// </summary>
        /// <returns></returns>


        [DllImport("./vnx_fmsynth.dll", EntryPoint = "fnLMS_GetNumDevices", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int fnLMS_GetNumDevices();

        [DllImport("./vnx_fmsynth.dll", EntryPoint = "fnLMS_SetTraceLevel", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern void fnLMS_SetTraceLevel(int tracelevel, int IOtracelevel, Int32 verbose);
        
        [DllImport("./vnx_fmsynth.dll", EntryPoint = "fnLMS_SetTestMode", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern void fnLMS_SetTestMode(Int32 mode);

        [DllImport("./vnx_fmsynth.dll", EntryPoint = "fnLMS_GetDevInfo", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int fnLMS_GetDevInfo(UInt32[] pActiveDevices);

        [DllImport("./vnx_fmsynth.dll", EntryPoint = "fnLMS_InitDevice", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int fnLMS_InitDevice(UInt32 DeviceID);

        [DllImport("./vnx_fmsynth.dll", EntryPoint = "fnLMS_CloseDevice", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int fnLMS_CloseDevice(UInt32 DeviceID);

        [DllImport("./vnx_fmsynth.dll", EntryPoint = "fnLMS_GetSerialNumber", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int fnLMS_GetSerialNumber(UInt32 DeviceID);

        [DllImport("./vnx_fmsynth.dll", EntryPoint = "fnLMS_GetModelName", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int fnLMS_GetModelName(UInt32 deviceID, byte[] pModelName);

        [DllImport("./vnx_fmsynth.dll", EntryPoint = "fnLMS_GetDLLVersion", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int fnLMS_GetDLLVersion();

        [DllImport("./vnx_fmsynth.dll", EntryPoint = "fnLMS_GetDeviceStatus", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int fnLMS_GetDeviceStatus(UInt32 deviceID);

        [DllImport("./vnx_fmsynth.dll", EntryPoint = "fnLMS_SetFrequency", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int fnLMS_SetFrequency(UInt32 deviceID, int frequency);

        [DllImport("./vnx_fmsynth.dll", EntryPoint = "fnLMS_SetStartFrequency", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int fnLMS_SetStartFrequency(UInt32 deviceID, int startfrequency);

        [DllImport("./vnx_fmsynth.dll", EntryPoint = "fnLMS_SetEndFrequency", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int fnLMS_SetEndFrequency(UInt32 deviceID, int endfrequency);

        [DllImport("./vnx_fmsynth.dll", EntryPoint = "fnLMS_SetSweepTime", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int fnLMS_SetSweepTime(UInt32 deviceID, int sweeptime);

        [DllImport("./vnx_fmsynth.dll", EntryPoint = "fnLMS_SetPowerLevel", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int fnLMS_SetPowerLevel(UInt32 deviceID, int powerlevel);

        [DllImport("./vnx_fmsynth.dll", EntryPoint = "fnLMS_SetRFOn", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int fnLMS_SetRFOn(UInt32 deviceID, int on);

        [DllImport("./vnx_fmsynth.dll", EntryPoint = "fnLMS_SetPulseOnTime", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int fnLMS_SetPulseOnTime(UInt32 deviceID, float pulseontime);
        
        [DllImport("./vnx_fmsynth.dll", EntryPoint = "fnLMS_SetPulseOffTime", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int fnLMS_SetPulseOffTime(UInt32 deviceID, float pulseofftime);

        [DllImport("./vnx_fmsynth.dll", EntryPoint = "fnLMS_EnableInternalPulseMod", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int fnLMS_EnableInternalPulseMod(UInt32 deviceID, int on);

        [DllImport("./vnx_fmsynth.dll", EntryPoint = "fnLMS_SetUseExternalPulseMod", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int fnLMS_SetUseExternalPulseMod(UInt32 deviceID, int external);

        [DllImport("./vnx_fmsynth.dll", EntryPoint = "fnLMS_SetFastPulsedOutput", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int fnLMS_SetFastPulsedOutput(UInt32 deviceID, float pulseontime, float pulsereptime, int on);

        [DllImport("./vnx_fmsynth.dll", EntryPoint = "fnLMS_SetUseInternalRef", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int fnLMS_SetUseInternalRef(UInt32 deviceID, int src_internal);

        [DllImport("./vnx_fmsynth.dll", EntryPoint = "fnLMS_SetSweepDirection", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int fnLMS_SetSweepDirection(UInt32 deviceID, int up);

        [DllImport("./vnx_fmsynth.dll", EntryPoint = "fnLMS_SetSweepMode", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int fnLMS_SetSweepMode(UInt32 deviceID, int mode);

        [DllImport("./vnx_fmsynth.dll", EntryPoint = "fnLMS_SetSweepType", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int fnLMS_SetSweepType(UInt32 deviceID, int swptype);

        [DllImport("./vnx_fmsynth.dll", EntryPoint = "fnLMS_StartSweep", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int fnLMS_StartSweep(UInt32 deviceID, int go);

        [DllImport("./vnx_fmsynth.dll", EntryPoint = "fnLMS_SaveSettings", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int fnLMS_SaveSettings(UInt32 deviceID);

        [DllImport("./vnx_fmsynth.dll", EntryPoint = "fnLMS_GetFrequency", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int fnLMS_GetFrequency(UInt32 deviceID);

        [DllImport("./vnx_fmsynth.dll", EntryPoint = "fnLMS_GetStartFrequency", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int fnLMS_GetStartFrequency(UInt32 deviceID);

        [DllImport("./vnx_fmsynth.dll", EntryPoint = "fnLMS_GetEndFrequency", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int fnLMS_GetEndFrequency(UInt32 deviceID);

        [DllImport("./vnx_fmsynth.dll", EntryPoint = "fnLMS_GetSweepTime", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int fnLMS_GetSweepTime(UInt32 deviceID);

        [DllImport("./vnx_fmsynth.dll", EntryPoint = "fnLMS_GetUseInternalRef", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int fnLMS_GetUseInternalRef(UInt32 deviceID);

        [DllImport("./vnx_fmsynth.dll", EntryPoint = "fnLMS_GetPowerLevel", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int fnLMS_GetPowerLevel(UInt32 deviceID);

        [DllImport("./vnx_fmsynth.dll", EntryPoint = "fnLMS_GetAbsPowerLevel", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int fnLMS_GetAbsPowerLevel(UInt32 deviceID);

        [DllImport("./vnx_fmsynth.dll", EntryPoint = "fnLMS_GetMaxPwr", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int fnLMS_GetMaxPwr(UInt32 deviceID);

        [DllImport("./vnx_fmsynth.dll", EntryPoint = "fnLMS_GetMinPwr", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int fnLMS_GetMinPwr(UInt32 deviceID);

        [DllImport("./vnx_fmsynth.dll", EntryPoint = "fnLMS_GetMaxFreq", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int fnLMS_GetMaxFreq(UInt32 deviceID);

        [DllImport("./vnx_fmsynth.dll", EntryPoint = "fnLMS_GetMinFreq", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int fnLMS_GetMinFreq(UInt32 deviceID);

        [DllImport("./vnx_fmsynth.dll", EntryPoint = "fnLMS_GetPulseOnTime", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int fnLMS_GetPulseOnTime(UInt32 deviceID);

        [DllImport("./vnx_fmsynth.dll", EntryPoint = "fnLMS_GetPulseOffTime", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int fnLMS_GetPulseOffTime(UInt32 deviceID);

        [DllImport("./vnx_fmsynth.dll", EntryPoint = "fnLMS_GetPulseMode", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int fnLMS_GetPulseMode(UInt32 deviceID);

        [DllImport("./vnx_fmsynth.dll", EntryPoint = "fnLMS_GetRF_On", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int fnLMS_GetRF_On(UInt32 deviceID);

        [DllImport("./vnx_fmsynth.dll", EntryPoint = "fnLMS_GetHasFastPulseMode", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int fnLMS_GetHasFastPulseMode(UInt32 deviceID);

        [DllImport("./vnx_fmsynth.dll", EntryPoint = "GetUseInternalPulseMod", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int fnLMS_GetUseInternalPulseMod(UInt32 deviceID);
    }

}
