using System;
using System.Runtime.InteropServices;
using System.Text;

namespace ltrModulesNet
{
    public class ltr51api
    {
        [DllImport("ltr51api.dll")]
        static extern _LTRNative.LTRERROR LTR51_Init(ref TLTR51 module);
        [DllImport("ltr51api.dll")]
        static extern _LTRNative.LTRERROR LTR51_Close(ref TLTR51 module);
        [DllImport("ltr51api.dll")]
        static extern _LTRNative.LTRERROR LTR51_Open(ref TLTR51 module, uint saddr,
            ushort sport, string csn, int slot_num, string ttf_name);
        [DllImport("ltr51api.dll")]
        static extern _LTRNative.LTRERROR LTR51_IsOpened(ref TLTR51 module);


        [DllImport("ltr51api.dll")]
        static extern uint LTR51_CreateLChannel(int PhysChannel, ref double HighThreshold,
            ref double LowThreshold, ThresholdRange ThresholdRange, EdgeMode EdgeMode);

        [DllImport("ltr51api.dll")]
        static extern _LTRNative.LTRERROR LTR51_GetThresholdVals(ref TLTR51 module, int LChNumber,
                    out double HighThreshold, out double LowThreshold, ThresholdRange ThresholdRange);

        [DllImport("ltr51api.dll")]
        static extern uint LTR51_CalcTimeOut(ref TLTR51 module, int n);

        [DllImport("ltr51api.dll")]
        static extern _LTRNative.LTRERROR LTR51_Config(ref TLTR51 module);
        [DllImport("ltr51api.dll")]
        static extern _LTRNative.LTRERROR LTR51_Start(ref TLTR51 module);
        [DllImport("ltr51api.dll")]
        static extern _LTRNative.LTRERROR LTR51_Stop(ref TLTR51 module);

        [DllImport("ltr51api.dll")]
        static extern int LTR51_Recv(ref TLTR51 hnd, uint[] buf, uint[] tmark, uint size, uint timeout); //Прием данных от модуля		

        [DllImport("ltr51api.dll")]
        static extern _LTRNative.LTRERROR LTR51_ProcessData(ref TLTR51 hnd, uint[] src_data, uint[] dst_data,
            double[] Frequency, ref uint size);
        
        [DllImport("ltr51api.dll")]
        static extern _LTRNative.LTRERROR LTR51_WriteEEPROM(ref TLTR51 module, int Address, byte val);

        [DllImport("ltr51api.dll")]
        static extern _LTRNative.LTRERROR LTR51_ReadEEPROM(ref TLTR51 module, int Address, out byte val);


        [DllImport("ltr51api.dll")]
        static extern IntPtr LTR51_GetErrorString(int err);


        public const double LTR51_K_RANGE_1_2 = -1.6737;
        public const double LTR51_K_RANGE_10 = -0.2010;
        public const double LTR51_UREF_VALUE = 2.048;

        public const uint LTR51_BASE_VAL_MIN = 70;
        public const double LTR51_FS_MAX = 500000;

        public const uint LTR51_MEZZANINES_CNT = 8;
        public const uint LTR51_MAZZANINE_CHANNELS_CNT = 2;
        public const uint LTR51_CHANNELS_CNT = LTR51_MEZZANINES_CNT * LTR51_MAZZANINE_CHANNELS_CNT;

        public enum ThresholdRange : int
        {
            Range_10V = 0,
            Range_1_2V = 1
        }

        public enum EdgeMode : int
        {
            RISE = 0,
            FALL = 1
        }



        [StructLayout(LayoutKind.Sequential, Pack = 4)]
        public struct INFO
        {
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 15)]
            char[] _name;
            byte _modification;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 24)]
            char[] _serial;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
            char[] _firmware_version;// Версия прошивки AVR
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
            char[] _firmware_date;  // Дата создания данной версии прошивки AVR  
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
            char[] _fpga_version; // Версия прошивки ПЛИС

            public string Name { get { return new string(_name).Split('\0')[0]; } }
            public string Serial { get { return new string(_serial).Split('\0')[0]; } }
            public string FirmwareVersion { get { return new string(_firmware_version).Split('\0')[0]; } }
            public string FirmwareDate { get { return new string(_firmware_date).Split('\0')[0]; } }
            public string FPGA_Version { get { return new string(_fpga_version).Split('\0')[0]; } }
        };


        [StructLayout(LayoutKind.Sequential, Pack = 4)]
        struct TLTR51
        {
            int size;   // размер структуры    
            public _LTRNative.TLTR Channel;
            ushort ChannelsEna_;
            int SetUserPars_;
            int LChQnt_;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
            public uint[] LChTbl;
            double Fs_;
            ushort Base_;
            double F_Base_;
            int AcqTime_;  // Время сбора в миллисекундах       
            int TbaseQnt_; // Количество периодов измерений, необходимое для обеспечения указанного интревала измерения
            INFO ModuleInfo_;

            public ushort ChannelsEna { get { return ChannelsEna_; } }
            public bool SetUserPars { get { return SetUserPars_ != 0; } set { SetUserPars_ = value ? 1 : 0; } }
            public int LChQnt { get { return LChQnt_; } set { LChQnt_ = value; } }
            public double Fs { get { return Fs_; } set { Fs_ = value; } }
            public ushort Base { get { return Base_; } set { Base_ = value; } }
            public double F_Base { get { return F_Base_; } }
            public int AcqTime { get { return AcqTime_; } set { AcqTime_ = value; } }
            public int TbaseQnt { get { return TbaseQnt_; } }

            public INFO ModuleInfo { get { return ModuleInfo_; } }
        }; // Структура описания модуля



        TLTR51 module;

        public ltr51api() 
        {
            LTR51_Init(ref module);	
        }

        ~ltr51api()
        {
            LTR51_Close(ref module);
        }

		
		public virtual _LTRNative.LTRERROR Init()
		{
			return LTR51_Init(ref module);
		}

        public virtual _LTRNative.LTRERROR Open(uint saddr, ushort sport, string csn, ushort cc, string ttf_name)
		{
            return LTR51_Open(ref module, saddr, sport, csn, cc, ttf_name);
		}

        public virtual _LTRNative.LTRERROR Open(string csn, ushort cc, string ttf_name)
        {
            return Open(_LTRNative.SADDR_DEFAULT, _LTRNative.SPORT_DEFAULT, csn, cc, ttf_name);
        }

        public virtual _LTRNative.LTRERROR Open(ushort cc, string ttf_name)
        {
            return Open("", cc, ttf_name);
        }

        public virtual _LTRNative.LTRERROR Open(uint saddr, ushort sport, string csn, ushort cc)
        {
            return Open(saddr, sport, csn, cc, "");
        }

        public virtual _LTRNative.LTRERROR Open(string csn, ushort cc)
        {
            return Open(csn, cc, "");
        }

        public virtual _LTRNative.LTRERROR Open(ushort cc)
        {
            return Open(cc, "");
        }


        public virtual _LTRNative.LTRERROR Close ()
		{
			return LTR51_Close(ref module);
		}        

        public virtual _LTRNative.LTRERROR IsOpened()
		{
			return LTR51_IsOpened(ref module);
		}




        public uint CalcTimeOut(int n)
        {
            return LTR51_CalcTimeOut(ref module, n);
        }

        public _LTRNative.LTRERROR Config()
        {
            return LTR51_Config(ref module);
        }
        public _LTRNative.LTRERROR Start()
        {
            return LTR51_Start(ref module);
        }
        public _LTRNative.LTRERROR Stop()
        {
            return LTR51_Stop(ref module);
        }

        public virtual int Recv(uint[] Data, uint[] tstamp, uint size, uint timeout)
        {
            return LTR51_Recv(ref module, Data, tstamp, size, timeout);
        }

        public virtual int Recv(uint[] Data, uint size, uint timeout)
        {
            return LTR51_Recv(ref module, Data, null, size, timeout);
        }

        public virtual _LTRNative.LTRERROR ProcessData(uint[] src, uint[] dest,
            double[] Frequency, ref uint size)
        {
            return LTR51_ProcessData(ref module, src, dest, Frequency, ref size);
        }

        public virtual _LTRNative.LTRERROR ProcessData(uint[] src,  double[] Frequency, uint size)
        {
            return LTR51_ProcessData(ref module, src, null, Frequency, ref size);
        }

        public virtual _LTRNative.LTRERROR ProcessData(uint[] src, uint[] dest, ref uint size)
        {
            return LTR51_ProcessData(ref module, src, dest, null, ref size);
        }


        public virtual _LTRNative.LTRERROR WriteEEPROM(int Address, byte val)
        {
            return LTR51_WriteEEPROM(ref module, Address, val);
        }

        public virtual _LTRNative.LTRERROR ReadEEPROM(int Address, out byte val)
        {
            return LTR51_ReadEEPROM(ref module, Address, out val);
        }        

        public virtual _LTRNative.LTRERROR SetDefaultTimeout(uint timeout)
        {
            return _LTRNative.LTR_SetTimeout(ref module.Channel, timeout);
        }


        public static string GetErrorString(_LTRNative.LTRERROR err)
        {
            IntPtr ptr = LTR51_GetErrorString((int)err);
            string str = Marshal.PtrToStringAnsi(ptr);
            Encoding srcEncodingFormat = Encoding.GetEncoding("windows-1251");
            Encoding dstEncodingFormat = Encoding.UTF8;
            return dstEncodingFormat.GetString(Encoding.Convert(srcEncodingFormat, dstEncodingFormat, srcEncodingFormat.GetBytes(str)));
        }

        public virtual _LTRNative.LTRERROR FillLChannel(
                int lch, int PhysChannel, ref double HighThreshold,
                ref double LowThreshold, ThresholdRange ThresholdRange, EdgeMode EdgeMode)
        {
            module.LChTbl[lch] = LTR51_CreateLChannel(PhysChannel, ref HighThreshold, ref LowThreshold,
                ThresholdRange, EdgeMode);
            return _LTRNative.LTRERROR.OK;
        }

        public virtual _LTRNative.LTRERROR FillLChannel(
            int lch, int PhysChannel, 
            double HighThreshold, double LowThreshold, 
            ThresholdRange ThresholdRange, EdgeMode EdgeMode)
        {
            module.LChTbl[lch] = LTR51_CreateLChannel(PhysChannel, ref HighThreshold, ref LowThreshold,
                ThresholdRange, EdgeMode);
            return _LTRNative.LTRERROR.OK;
        }

        public virtual _LTRNative.LTRERROR GetThresholdVals(
            int lch, out double HighThreshold, out double LowThreshold, ThresholdRange ThresholdRange)
        {
            return LTR51_GetThresholdVals(ref module, lch, out HighThreshold, out LowThreshold, ThresholdRange);
        }


        public ushort ChannelsEna { get { return module.ChannelsEna; } }
        public bool SetUserPars { get { return module.SetUserPars; } set { module.SetUserPars = value; } }
        public int LChQnt { get { return module.LChQnt; } set { module.LChQnt = value; } }
        public double Fs { get { return module.Fs; } set { module.Fs = value; } }
        public ushort Base { get { return module.Base; } set { module.Base = value; } }
        public double F_Base { get { return module.F_Base; } }
        public int AcqTime { get { return module.AcqTime; } set { module.AcqTime = value; } }
        public int TbaseQnt { get { return module.TbaseQnt; } }

        public INFO ModuleInfo { get { return module.ModuleInfo; } }
    }
}
