using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Net;
using System.Net.NetworkInformation;




namespace ltrModulesNet
{
    public class ltr030api
    {
        [DllImport("ltr030api.dll")]
        static extern _LTRNative.LTRERROR LTR030_Init (ref TLTR030 module);
        [DllImport("ltr030api.dll")]
        static extern _LTRNative.LTRERROR LTR030_Open(ref TLTR030 hnd, uint saddr, ushort sport, ushort iface, string csn);
        [DllImport("ltr030api.dll")]
        static extern _LTRNative.LTRERROR LTR030_Close(ref TLTR030 hnd);

        [DllImport("ltr030api.dll")]
        static extern _LTRNative.LTRERROR LTR030_SetInterfaceUsb(ref TLTR030 hnd);
        [DllImport("ltr030api.dll")]
        static extern _LTRNative.LTRERROR LTR030_SetInterfaceTcp(ref TLTR030 hnd, uint ip_addr, uint ip_mask, uint gate);
        [DllImport("ltr030api.dll")]
        static extern _LTRNative.LTRERROR LTR030_FlashWrite(ref TLTR030 hnd, uint addr, byte[] data, uint size);
        [DllImport("ltr030api.dll")]
        static extern _LTRNative.LTRERROR LTR030_FlashRead(ref TLTR030 hnd, uint addr, byte[] data, uint size);
        [DllImport("ltr030api.dll")]
        static extern _LTRNative.LTRERROR LTR030_LoadDspFirmware(ref TLTR030 hnd, string filename, IntPtr progr_cb, IntPtr cb_data);
        [DllImport("ltr030api.dll")]
        static extern _LTRNative.LTRERROR LTR030_LoadDspFirmware(ref TLTR030 hnd, string filename, LOAD_PROGR_CB progr_cb, IntPtr cb_data);
        [DllImport("ltr030api.dll")]
        static extern _LTRNative.LTRERROR LTR030_LoadFpgaFirmware(ref TLTR030 hnd, string filename, IntPtr progr_cb, IntPtr cb_data);
        [DllImport("ltr030api.dll")]
        static extern _LTRNative.LTRERROR LTR030_LoadFpgaFirmware(ref TLTR030 hnd, string filename, LOAD_PROGR_CB progr_cb, IntPtr cb_data);
        [DllImport("ltr030api.dll")]
        static extern _LTRNative.LTRERROR LTR030_GetConfig(ref TLTR030 hnd, out CONFIG cfg);
        [DllImport("ltr030api.dll")]
        static extern _LTRNative.LTRERROR LTR030_SetConfig(ref TLTR030 hnd, ref CONFIG cfg);
        [DllImport("ltr030api.dll")]
        static extern _LTRNative.LTRERROR LTR030_GetFactoryMac(ref TLTR030 hnd, byte[] mac);
        [DllImport("ltr030api.dll")]
        static extern _LTRNative.LTRERROR LTR030_CrateReset(ref TLTR030 hnd);
        [DllImport("ltr030api.dll")]
        static extern IntPtr LTR030_GetErrorString(int err);



        [StructLayout(LayoutKind.Sequential, Pack=4)]
        public struct CONFIG {
            ushort _size;
            ushort _interface;
            uint   _IpAddr;
            uint   _Gateway;
            uint   _IpMask;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
            byte[]   _UserMac;

            ltrcrate.Interfaces Interface { get { return (ltrcrate.Interfaces)_interface; } set { _interface = (ushort)value; } }
            IPAddress IpAddr { get { return NetAddrConverter.uintToIpAddr(_IpAddr); } set { _IpAddr = NetAddrConverter.ipAddrToUint(value); } }
            IPAddress Gateway { get { return NetAddrConverter.uintToIpAddr(_Gateway); } set { _Gateway = NetAddrConverter.ipAddrToUint(value); } }
            IPAddress IpMask { get { return NetAddrConverter.uintToIpAddr(_IpMask); } set { _IpMask = NetAddrConverter.ipAddrToUint(value); } }
            PhysicalAddress UserMac
            {
                get { return new PhysicalAddress(_UserMac); }
                set
                {
                    byte[] vals = value.GetAddressBytes();
                    for (int i = 0; i < _UserMac.Length; i++)
                    {
                        _UserMac[i] = i < vals.Length ? vals[i] : (byte)0;
                    }
                }
            }
        }

        [StructLayout(LayoutKind.Sequential, Pack=4)]
        struct TLTR030
        {
            int _size;
            _LTRNative.TLTR _channel;
            IntPtr _internal; 
            ltrcrate.Info _info;

            public ltrcrate.Info Info {get {return _info;}}
        };   
 
        
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate void LOAD_PROGR_CB(uint stage, uint done_size, uint full_size, IntPtr cb_data);

        TLTR030 hnd;

        public _LTRNative.LTRERROR Open(uint saddr, ushort sport, ltrcrate.Interfaces iface, string csn)
        {
            return LTR030_Open(ref hnd, saddr, sport, (ushort)iface, csn);
        }

        public _LTRNative.LTRERROR Open(ltrcrate.Interfaces iface, string csn)
        {
            return Open(_LTRNative.SADDR_DEFAULT, _LTRNative.SPORT_DEFAULT, iface, csn);
        }

        public _LTRNative.LTRERROR Open(string csn)
        {
            return Open(_LTRNative.SADDR_DEFAULT, _LTRNative.SPORT_DEFAULT, ltrcrate.Interfaces.UNKNOWN, csn);
        }

        public _LTRNative.LTRERROR Close()
        {
            return LTR030_Close(ref hnd);
        }

        public _LTRNative.LTRERROR SetInterfaceUsb()
        {
            return LTR030_SetInterfaceUsb(ref hnd);
        }


        public _LTRNative.LTRERROR SetInterfaceTcp(IPAddress ip_addr, IPAddress ip_mask, IPAddress gate)
        {
            return LTR030_SetInterfaceTcp(ref hnd,
                NetAddrConverter.ipAddrToUint(ip_addr),
                NetAddrConverter.ipAddrToUint(ip_mask),
                NetAddrConverter.ipAddrToUint(gate));
        }

        public _LTRNative.LTRERROR GetConfig(out CONFIG config)
        {
            return LTR030_GetConfig(ref hnd, out config);
        }
        public _LTRNative.LTRERROR SetConfig(ref CONFIG cfg)
        {
            return LTR030_SetConfig(ref hnd, ref cfg);
        }
        public _LTRNative.LTRERROR GetFactoryMac(out PhysicalAddress mac)
        {
            byte[] mac_bytes = new byte[6];
            _LTRNative.LTRERROR err = LTR030_GetFactoryMac(ref hnd, mac_bytes);
            mac = new PhysicalAddress(mac_bytes);            
            return err;
        }

        public _LTRNative.LTRERROR CrateReset()
        {
            return LTR030_CrateReset(ref hnd);
        }


        ltrcrate.Info Info { get { return hnd.Info; } }

        public static string GetErrorString(_LTRNative.LTRERROR err)
        {
            IntPtr ptr = LTR030_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)));
        }
    }
}
