using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.ServiceModel.Discovery;
using System.Text;
using System.Xml;

namespace YoseenPTZ.SDKDef
{
    public static class LibPTZ
    {
        //
        public const int PresetConfig_PresetCountMax = 500;
        public const int Preset_Size = 96;

        //
        [DllImport("LibPTZ.dll", EntryPoint = "Device_InitSDK", CallingConvention = CallingConvention.Cdecl)]
        public extern static int Device_InitSDK();

        [DllImport("LibPTZ.dll", EntryPoint = "Device_FreeSDK", CallingConvention = CallingConvention.Cdecl)]
        public extern static void Device_FreeSDK();

        [DllImport("LibPTZ.dll", EntryPoint = "Device_Create", CallingConvention = CallingConvention.Cdecl)]
        public extern static IntPtr Device_Create();

        [DllImport("LibPTZ.dll", EntryPoint = "Device_Free", CallingConvention = CallingConvention.Cdecl)]
        public extern static void Device_Free(ref IntPtr pp);

        [DllImport("LibPTZ.dll", EntryPoint = "Device_PresetOpenConfig", CallingConvention = CallingConvention.Cdecl)]
        public extern static int Device_PresetOpenConfig(IntPtr context, string fn, ref IntPtr config);

        [DllImport("LibPTZ.dll", EntryPoint = "Device_PresetCloseConfig", CallingConvention = CallingConvention.Cdecl)]
        public extern static void Device_PresetCloseConfig(IntPtr context);

        [DllImport("LibPTZ.dll", EntryPoint = "Device_PresetSave", CallingConvention = CallingConvention.Cdecl)]
        public extern static int Device_PresetSave(IntPtr context, ref Preset preset, int presetId);

        [DllImport("LibPTZ.dll", EntryPoint = "Device_PresetGoto", CallingConvention = CallingConvention.Cdecl)]
        public extern static int Device_PresetGoto(IntPtr context, int presetId);

        [DllImport("LibPTZ.dll", EntryPoint = "Device_SetDeviceConfig", CallingConvention = CallingConvention.Cdecl)]
        public extern static int Device_SetDeviceConfig(IntPtr context, ref DeviceConfig config);

        [DllImport("LibPTZ.dll", EntryPoint = "Device_Login", CallingConvention = CallingConvention.Cdecl)]
        public extern static int Device_Login(IntPtr context);

        [DllImport("LibPTZ.dll", EntryPoint = "Device_Logout", CallingConvention = CallingConvention.Cdecl)]
        public extern static int Device_Logout(IntPtr context);

        [DllImport("LibPTZ.dll", EntryPoint = "Device_PTZControlStart", CallingConvention = CallingConvention.Cdecl)]
        public extern static int Device_PTZControlStart(IntPtr context, int act, int arg);

        [DllImport("LibPTZ.dll", EntryPoint = "Device_PTZControlStop", CallingConvention = CallingConvention.Cdecl)]
        public extern static int Device_PTZControlStop(IntPtr context, int act, int arg);

        [DllImport("LibPTZ.dll", EntryPoint = "Device_PTZW4R4", CallingConvention = CallingConvention.Cdecl)]
        public extern static int Device_PTZW4R4(IntPtr context, int w, ref int r);

        [DllImport("LibPTZ.dll", EntryPoint = "Device_SetPTZ", CallingConvention = CallingConvention.Cdecl)]
        public extern static int Device_SetPTZ(IntPtr context, int pan, int tilt, int zoom);

        [DllImport("LibPTZ.dll", EntryPoint = "Device_GetPTZ", CallingConvention = CallingConvention.Cdecl)]
        public extern static int Device_GetPTZ(IntPtr context, ref int pan, ref int tilt, ref int zoom);

        [DllImport("LibPTZ.dll", EntryPoint = "Device_IRSetImageConfig", CallingConvention = CallingConvention.Cdecl)]
        public extern static int Device_IRSetImageConfig(IntPtr context, ref ImageConfig config);

        [DllImport("LibPTZ.dll", EntryPoint = "Device_IRSaveFrame", CallingConvention = CallingConvention.Cdecl)]
        public extern static int Device_IRSaveFrame(IntPtr context, string fn);

        [DllImport("LibPTZ.dll", EntryPoint = "Device_IRSendControl", CallingConvention = CallingConvention.Cdecl)]
        public extern static int Device_IRSendControl(IntPtr context, ref Ctl ctl);

        [DllImport("LibPTZ.dll", EntryPoint = "Device_IRSendControlX", CallingConvention = CallingConvention.Cdecl)]
        public extern static int Device_IRSendControlX(IntPtr context, ref CtlX ctl);

        [DllImport("LibPTZ.dll", EntryPoint = "Device_VISSaveFrame", CallingConvention = CallingConvention.Cdecl)]
        public extern static int Device_VISSaveFrame(IntPtr context, string fn);

        [DllImport("LibPTZ.dll", EntryPoint = "Device_StartPreview", CallingConvention = CallingConvention.Cdecl)]
        public extern static int Device_StartPreview(IntPtr context, ref DevicePreviewInfo previewInfo);

        [DllImport("LibPTZ.dll", EntryPoint = "Device_StopPreview", CallingConvention = CallingConvention.Cdecl)]
        public extern static int Device_StopPreview(IntPtr context);

        [DllImport("LibPTZ.dll", EntryPoint = "Device_BeginSave", CallingConvention = CallingConvention.Cdecl)]
        public extern static int Device_BeginSave(IntPtr context, string fn, int ft);

        [DllImport("LibPTZ.dll", EntryPoint = "Device_EndSave", CallingConvention = CallingConvention.Cdecl)]
        public extern static int Device_EndSave(IntPtr context);


        [DllImport("LibPTZ.dll", EntryPoint = "Device_VISVoiceTalkStart", CallingConvention = CallingConvention.Cdecl)]
        public extern static int Device_VISVoiceTalkStart(IntPtr context);

        [DllImport("LibPTZ.dll", EntryPoint = "Device_VISVoiceTalkSetVolumn", CallingConvention = CallingConvention.Cdecl)]
        public extern static int Device_VISVoiceTalkSetVolumn(IntPtr context, int volumn);

        [DllImport("LibPTZ.dll", EntryPoint = "Device_VISVoiceTalkStop", CallingConvention = CallingConvention.Cdecl)]
        public extern static int Device_VISVoiceTalkStop(IntPtr context);
    }

    #region types
    public enum EPtzConnType
    {
        EPtzConnType_IR = 0,
        EPtzConnType_VIS,
    };

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct DeviceConfig
    {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
        public string ir_ip;

        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
        public string vis_ip;

        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string vis_username;

        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string vis_password;

        public int ptzconntype;

        public int timeout;//ms

        public void Reset()
        {
            ir_ip = "192.168.1.201";
            vis_ip = "192.168.1.202";
            vis_username = "admin";
            vis_password = "yoseen2018";
            ptzconntype = (int)EPtzConnType.EPtzConnType_IR;
            timeout = 0;
        }
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct ImageConfig
    {
        public int palette_type;

        public strech_control sc;

        public void Reset()
        {
            palette_type = (int)xxxpalette.IronBow;

            sc.strech_type = strech_type.STRECH_TYPE_PHE;
            sc.gain = 2.0f;
            sc.dde_level = 0;

            sc.man_enable = 0;
            sc.ct_type = ColorTempType.None;
        }
    }


    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Size = LibPTZ.Preset_Size)]
    public struct Preset
    {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
        public string name;
        public int pan;
        public int tilt;
        public int zoom;

    };


    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Size = 96 * LibPTZ.PresetConfig_PresetCountMax)]
    public struct PresetConfig
    {
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = LibPTZ.PresetConfig_PresetCountMax)]
        public Preset[] presetArray;
    };

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct DeviceFrame
    {
        public ushort width;
        public ushort height;
        public int pad;
        public IntPtr tempHead;
        public IntPtr temp;
        public IntPtr bmp;
    };

    public delegate void callback_onDeviceFrame(int errorCode, IntPtr frame, IntPtr custom);

    public enum EStreamType
    {
        EStreamType_None = 0,
        EStreamType_Temp,
        EStreamType_Video,
        EStreamType_Rtsp
    };

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct DevicePreviewInfo
    {
        public IntPtr userData;
        public int ir_streamType;
        public int ir_pad;
        public IntPtr ir_hwnd;
        public callback_onDeviceFrame ir_onFrame;

        public int vis_streamType;
        public int vis_pad;
        public IntPtr vis_hwnd;
        public callback_onDeviceFrame vis_onFrame;

        //
        public ushort ir_width;
        public ushort ir_height;
        public ushort vis_width;
        public ushort vis_height;
    };

    public enum EFileType
    {
        EFileType_mp4 = 0,
        EFileType_stream,
        EFileType_jpg
    };

    [Flags]
    public enum DeviceContextFlags
    {
        //
        DeviceContextFlags_IR_Login = 0x00000001,
        DeviceContextFlags_IR_Preview = 0x00000002,
        DeviceContextFlags_IR_Record = 0x00000004,

        DeviceContextFlags_VIS_Login = (DeviceContextFlags_IR_Login << 8),
        DeviceContextFlags_VIS_Preview = (DeviceContextFlags_IR_Preview << 8),
        DeviceContextFlags_VIS_Record = (DeviceContextFlags_IR_Record << 8),

        //combine
        DeviceContextFlags_IR_Login_Preview = DeviceContextFlags_IR_Login | DeviceContextFlags_IR_Preview,
        DeviceContextFlags_VIS_Login_Preview = DeviceContextFlags_VIS_Login | DeviceContextFlags_VIS_Preview,
        DeviceContextFlags_IR_Preview_Record = DeviceContextFlags_IR_Preview | DeviceContextFlags_IR_Record,
        DeviceContextFlags_VIS_Preview_Record = DeviceContextFlags_VIS_Preview | DeviceContextFlags_VIS_Record,
    };

    [Flags]
    public enum PTZFlags
    {
        PTZFlags_Pan = 0x01,
        PTZFlags_Tilt = 0x02,
        PTZFlags_Zoom = 0x04,

        //
        PTZFlags_All = PTZFlags_Pan | PTZFlags_Tilt | PTZFlags_Zoom
    };
    #endregion
}
