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

namespace ltrModulesNet
{
    public class ltr42api 
    {
        [DllImport("ltr42api.dll")]
        static extern _LTRNative.LTRERROR LTR42_Init(ref TLTR42 module);

        [DllImport("ltr42api.dll")]
        static extern _LTRNative.LTRERROR LTR42_Open(ref TLTR42 module, int net_addr, ushort net_port,
                                                     string crate_sn, int slot_num);
        [DllImport("ltr42api.dll")]
        static extern _LTRNative.LTRERROR LTR42_IsOpened(ref TLTR42 module);

        [DllImport("ltr42api.dll")]
        static extern _LTRNative.LTRERROR LTR42_Close(ref TLTR42 module);
            
        [DllImport("ltr42api.dll")]
        static extern _LTRNative.LTRERROR LTR42_Config(ref TLTR42 module);

        [DllImport("ltr42api.dll")]
        static extern _LTRNative.LTRERROR LTR42_WritePort(ref TLTR42 module, ushort OutputData);

        [DllImport("ltr42api.dll")]
        static extern _LTRNative.LTRERROR LTR42_WriteArray(ref TLTR42 module, ushort[] OutputArray, int ArraySize);
        
        [DllImport("ltr42api.dll")]
        static extern _LTRNative.LTRERROR LTR42_StartSecondMark(ref TLTR42 module);

        [DllImport("ltr42api.dll")]
        static extern _LTRNative.LTRERROR LTR42_StopSecondMark(ref TLTR42 module);

        [DllImport("ltr42api.dll")]
        static extern _LTRNative.LTRERROR LTR42_MakeStartMark(ref TLTR42 module);

        [DllImport("ltr42api.dll")]
        static extern _LTRNative.LTRERROR LTR42_WriteEEPROM(ref TLTR42 module, int Address, byte val);

        [DllImport("ltr42api.dll")]
        static extern _LTRNative.LTRERROR LTR42_ReadEEPROM(ref TLTR42 module, int Address, out byte val);

        [DllImport("ltr42api.dll")]
        static extern IntPtr LTR42_GetErrorString(int ErrorCode);

        [DllImport("ltr42api.dll")]
        static extern _LTRNative.LTRERROR LTR42_SetStartMarkPulseTime(ref TLTR42 module, uint time_mks);

        public const int LTR42_EEPROM_SIZE = 512;

        public enum MarkMode : int
        {
            INTERNAL = 0,
            MASTER = 1,
            EXTERNAL = 2
        }

        [StructLayout(LayoutKind.Sequential, Pack = 4)]
        public struct INFO
        {
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
            char[] Name_;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 24)]
            char[] Serial_;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
            char[] FirmwareVersion_;// Версия БИОСа
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
            char[] FirmwareDate_;  // Дата создания данной версии БИОСа

            public string Name { get { return new string(Name_).Split('\0')[0]; } }
            public string Serial { get { return new string(Serial_).Split('\0')[0]; } }
            public string FirmwareVersionStr { get { return new string(FirmwareVersion_).Split('\0')[0]; } }
            public string FirmwareDateStr { get { return new string(FirmwareDate_).Split('\0')[0]; } }
        };

        [StructLayout(LayoutKind.Sequential, Pack = 4)]
        public struct MarksCfg
        {
            MarkMode SecondMark_Mode_; // Режим меток. 0 - внутр., 1-внутр.+выход, 2-внешн
            MarkMode StartMark_Mode_; // 

            public MarkMode SecondMark_Mode { get { return SecondMark_Mode_; } set { SecondMark_Mode_ = value; } }
            public MarkMode StartMark_Mode { get { return StartMark_Mode_; } set { StartMark_Mode_ = value; } }
        };  // Структура для работы с временными метками
                /* Структура описания модуля */


        [StructLayout(LayoutKind.Sequential, Pack = 4)]
        struct TLTR42
        {
            public _LTRNative.TLTR Channel;
            int size;   // размер структуры    
            [MarshalAs(UnmanagedType.U1)]
            bool AckEna_;
            
            MarksCfg Marks_;
            INFO ModuleInfo_;

            public bool AckEna { get { return AckEna_; } set { AckEna_ = value; } }            
            public MarksCfg Marks { get { return Marks_; } set { Marks_ = value; } }
            public INFO ModuleInfo { get { return ModuleInfo_; } }
        }; // Структура описания модуля

        TLTR42 module;

        public ltr42api() 
        {
            LTR42_Init(ref module);	
        }

        ~ltr42api()
        {
            LTR42_Close(ref module);
        }

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

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

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

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

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

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

        public virtual _LTRNative.LTRERROR Config()
        {
            return LTR42_Config(ref module);
        }

        public virtual _LTRNative.LTRERROR WritePort(ushort OutputData)
        {
            return LTR42_WritePort(ref module, OutputData);
        }

        public virtual _LTRNative.LTRERROR WriteArray(ushort[] OutputArray, byte ArraySize)
        {
            return LTR42_WriteArray(ref module, OutputArray, ArraySize);
        }

        public virtual _LTRNative.LTRERROR StartSecondMark()
        {
            return LTR42_StartSecondMark(ref module);
        }

        public virtual _LTRNative.LTRERROR StopSecondMark()
        {
            return LTR42_StopSecondMark(ref module);
        }

        public virtual _LTRNative.LTRERROR MakeStartMark()
        {
            return LTR42_MakeStartMark(ref module);
        }

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

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

        public virtual _LTRNative.LTRERROR SetStartMarkPulseTime(uint time_ms)
        {
            return LTR42_SetStartMarkPulseTime(ref module, time_ms);
        }

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


        public static string GetErrorString(_LTRNative.LTRERROR err)
        {
            IntPtr ptr = LTR42_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 bool AckEna { get { return module.AckEna; } set { module.AckEna = value; } }
        public MarksCfg Marks { get { return module.Marks; } set { module.Marks = value; } }
        public INFO ModuleInfo { get { return module.ModuleInfo; } }
    }

}
