using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using VzClientSDKDemo;

namespace NumMachine
{
    /// <summary>
    /// 号牌机通信类
    /// </summary>
    public class NumberMachine
    {
        /// <summary>
        /// 车辆数据
        /// </summary>
        public class CarNumberInfo
        {
            public string plate_number;//号牌
            public string plate_color;//号牌颜色
            public string plate_type;//号牌类型
            public int plate_confidence;//号牌可信度
            public string recognition_time;//识别时间点
            public string plate_full_image;//号牌全景图
            public string plate_clip_image;//号牌特写图
            /// <summary>
            /// 构造函数
            /// </summary>
            public CarNumberInfo()
            {
                this.plate_number = "";
                this.plate_color = "";
                this.plate_full_image = "";
                this.plate_clip_image = "";
                this.plate_type = "";
                this.plate_confidence = 0;
                this.recognition_time = "";

            }
            /// <summary>
            /// 打印号牌信息
            /// </summary>
            public void Print()
            {
                Console.WriteLine("号牌:{0} 号牌颜色:{1} 号牌类型:{2} 号牌可信度:{3} 识别时间点:{4}\n号牌全景图:{5}\n号牌特写图:{6}", 
                this.plate_number, this.plate_color, this.plate_type, this.plate_confidence, this.recognition_time, this.plate_full_image.Length, this.plate_clip_image.Length);
            }
        }


        private string m_ip;//号牌机IP
        private ushort m_port;//端口
        private string m_user;//用户名
        private string m_password;//用户密码
        private int m_handle;//操作句柄
        private string m_sAppPath = System.IO.Directory.GetCurrentDirectory();//当前路径
        private bool m_isClose = false;//是否关闭
        private CarNumberInfo m_carData = new CarNumberInfo();//车辆数据
        VzClientSDK.VZLPRC_PLATE_INFO_CALLBACK m_callBack;//车牌回调



        /// <summary>
        /// 号牌机构造函数
        /// </summary>
        public NumberMachine(string ip,ushort port=80,string user="admin",string password="admin")
        {
            this.m_ip = ip;
            this.m_port = port; 
            this.m_user = user;
            this.m_password = password;

            if (VzClientSDK.VzLPRClient_Setup() != 0 )
            {
                Console.WriteLine("SDK未载入，初始化号牌机失败！");
                return;
            }
            m_handle = VzClientSDK.VzLPRClient_Open(m_ip, m_port, m_user, m_password);
            if (m_handle == 0)
                Console.WriteLine("打开设备失败！"+ this.m_ip);
            m_callBack = new VzClientSDK.VZLPRC_PLATE_INFO_CALLBACK(PlateInfoCallBack);

        }
        /// <summary>
        /// 返回号牌信息
        /// </summary>
        /// <returns></returns>
        public CarNumberInfo GetCarNumberInfo()
        {
            return this.m_carData;
        }
        /// <summary>
        /// 启动设备
        /// </summary>
        public void Start()
        {
            //设置号牌回调
            if (VzClientSDK.VzLPRClient_SetPlateInfoCallBack(m_handle, m_callBack, IntPtr.Zero, 1) == 0)
            {
                Console.WriteLine("号牌信息回调函数设置成功！");
            }
            else
            {
                Console.WriteLine("号牌信息回调函数设置失败！");
            }
            Task.Factory.StartNew(() =>
            {
                while (!m_isClose)
                {
                    if (!m_isClose)
                    {
                        byte pStatus = new byte();
                        VzClientSDK.VzLPRClient_IsConnected(this.m_handle,ref pStatus);
                        if (pStatus == 1 && this.m_handle > 0)
                        {
                            //获取号牌数据
                            VzClientSDK.VzLPRClient_ForceTrigger(m_handle);
                            this.m_carData.Print();
                        }
                        else
                        {
                            //重新连接
                            this.m_carData = new CarNumberInfo();
                            Console.WriteLine("号牌机断开连接！尝试重新连接中---- ip:"+this.m_ip);
                            m_handle = VzClientSDK.VzLPRClient_Open(m_ip, m_port, m_user, m_password);
                            VzClientSDK.VzLPRClient_SetPlateInfoCallBack(m_handle, m_callBack, IntPtr.Zero, 1);
                        }

                    }
                    //强制获取数据  500毫秒一次
                    Thread.Sleep(500);
                }
            });

        }
        /// <summary>
        /// 获取号牌类型
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        private string get_plate_type(int type)
        {
            switch (type)
            {
                case 1: return "蓝牌小汽车";
                case 2: return "黑牌小汽车";
                case 3: return "单排黄牌";
                case 4: return "双排黄牌(大车尾牌，农用车)";
                case 5: return "警车车牌";
                case 6: return "武警车牌";
                case 7: return "个性化车牌";
                case 8: return "单排军车牌";
                case 9: return "双排军车牌";
                case 10: return "使馆车牌";
                case 11: return "香港进出中国大陆车牌";
                case 12: return "农用车牌";
                case 13: return "教练车牌";
                case 14: return "澳门进出中国大陆车牌";
                case 15: return "双层武警车牌";
                case 16: return "武警总队车牌";
                case 17: return "双层武警总队车牌";
                case 18: return "民航";
                case 19: return "新能源小型车";
                case 20: return "无车牌";
            }
            return "未知车牌";
        }
        /// <summary>
        /// 号牌信息回调函数
        /// </summary>
        /// <param name="handle"></param>
        /// <param name="pUserData"></param>
        /// <param name="pResult"></param>
        /// <param name="uNumPlates"></param>
        /// <param name="eResultType"></param>
        /// <param name="pImgFull"></param>
        /// <param name="pImgPlateClip"></param>
        /// <returns></returns>
        private int PlateInfoCallBack(int handle, IntPtr pUserData, IntPtr pResult, uint uNumPlates, VzClientSDK.VZ_LPRC_RESULT_TYPE eResultType, IntPtr pImgFull, IntPtr pImgPlateClip)
        {
            if (eResultType != VzClientSDK.VZ_LPRC_RESULT_TYPE.VZ_LPRC_RESULT_REALTIME)
            {
                //获取SDK调用结果
                VzClientSDK.TH_PlateResult result = (VzClientSDK.TH_PlateResult)Marshal.PtrToStructure(pResult, typeof(VzClientSDK.TH_PlateResult));
                string strLicense = (new string(result.license)).Split('\0')[0];
                if (!strLicense.Contains("_无_"))
                {
                    if (result.nConfidence > m_carData.plate_confidence)
                    {
                        m_carData = new CarNumberInfo();
                        //车牌号
                        m_carData.plate_number = strLicense;
                        //车牌可信度
                        m_carData.plate_confidence = result.nConfidence;
                        //车牌类型
                        m_carData.plate_type = this.get_plate_type(result.nType);
                        //车牌颜色
                        string color = (new string(result.color)).Split('\0')[0];
                        m_carData.plate_color = color;
                        //获取时间点
                        DateTime now = DateTime.Now;
                        string sTime = string.Format("{0:yyyyMMddHHmmss}", now);
                        m_carData.recognition_time = sTime;

                        //string pImgPath = m_sAppPath + "\\image\\";
                        //if (!Directory.Exists(pImgPath))
                        //{
                        //    Directory.CreateDirectory(pImgPath);
                        //}
                        //string pImgFullName = pImgPath + strLicense + "_full.jpg";
                        //string pImgPlateClipName = pImgPath + strLicense + "_plate.jpg";
                        //车辆全景图
                        IntPtr pointer = Marshal.AllocHGlobal(1024 * 1024 * 2);
                        int length = VzClientSDK.VzLPRClient_ImageEncodeToJpeg(pImgFull, pointer, 1024 * 1024 * 2, 50);
                        if (length > 0)
                        {
                            byte[] bytes = new byte[length];
                            Marshal.Copy(pointer, bytes, 0, length);
                            m_carData.plate_full_image = Convert.ToBase64String(bytes);

                        }
                        else
                            m_carData.plate_full_image = "";
                        Marshal.FreeHGlobal(pointer);
                        //号牌特写图
                        pointer = Marshal.AllocHGlobal(1024 * 1024 * 2);
                        length = VzClientSDK.VzLPRClient_ImageEncodeToJpeg(pImgPlateClip, pointer, 1024 * 1024 * 2, 50);
                        if (length > 0)
                        {
                            byte[] bytes = new byte[length];
                            Marshal.Copy(pointer, bytes, 0, length);
                            m_carData.plate_clip_image = Convert.ToBase64String(bytes);
                        }
                        else
                            m_carData.plate_clip_image = "";
                        Marshal.FreeHGlobal(pointer);
                    }
                }
                else
                    m_carData = new CarNumberInfo();
            }

            return 0;
        }
        /// <summary>
        /// 关闭设备
        /// </summary>
        public void Close()
        {
            this.m_isClose = true;
            if (VzClientSDK.VzLPRClient_Close(m_handle) == 0)
                Console.WriteLine("关闭设备成功！");
            VzClientSDK.VzLPRClient_Cleanup();
        }
    }
}
