//*****************************************************************************
//
//   中国航天科工集团第二研究院
//    北京无线电计量测试研究所
//
// 项目名称: 嵌入式虹膜考勤系统
// 项目版本: 2019.11.27 识别产品化-开始
//
//*****************************************************************************
using System;
using System.Windows.Forms;
using System.Threading;
using System.Reflection;
using System.Drawing;
using irisRefactor.IrisSound;
using System.Data;
using irisHelper;
using IrisDoor;
using irisDataBase;
using irisDataBase.Model;
using irisPrint.service;
using irisPrint.Impl;
using System.Runtime.InteropServices;
using System.Drawing.Imaging;
using OpenCvSharp;
using OpenCvSharp.Extensions;

namespace irisRefactor.FrmService
{
    public partial class Form1 : Form
    {
        [DllImport("ar_temp.dll", EntryPoint = "Init")]
        public static extern unsafe void Init();

        [DllImport("ar_temp.dll", EntryPoint = "ExpData")]
        public static extern unsafe void ExpData(ref byte* imageFrame, ref byte* tempFrame);

        private static Form1 _form1 = null;
        public static Form1 GetInstance()
        {
            if (_form1 == null)
                _form1 = new Form1();

            return _form1;
        }

        private Form1()
        {
            try
            {
                InitializeComponent();
                // 设置双缓冲
                SetStyle(ControlStyles.UserPaint, true);
                SetStyle(ControlStyles.AllPaintingInWmPaint, true);
                SetStyle(ControlStyles.OptimizedDoubleBuffer, true);

                pic_retry.Visible = false;
                pic_retryEn.Visible = false;

                Form1.CheckForIllegalCrossThreadCalls = false;
            }
            catch (Exception e)
            {
                MessageBox.Show("fail: " + e);
            }
        }

        private void Form1_Shown(object sender, EventArgs e)
        {
            //测温
            Thread mcDispThread = new Thread(mcDisp);
            mcDispThread.Start();
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            try
            {
                ProMemory.Close();

                Environment.Exit(0);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "close..." + ex.Message, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        #region 外部调用方法

        public void mcDisp()
        {
            if (ProMemory.appConfig.TempType == 1)
                axMC_DISP1.open();
            else if (ProMemory.appConfig.TempType == 2)
            {
                showTempPic();
            }
        }
        /// <summary>
        /// 重置界面，恢复默认界面
        /// </summary>
        public void ReInitialize()
        {
            try
            {
                if (this.IsHandleCreated)
                {
                    Invoke(new MethodInvoker(delegate ()
                    {
                        picLive.Visible = true;
                        pictureBox1.Visible = true;
                        pictureBox2.Visible = true;
                        pictureBox3.Visible = true;
                        pictureBox4.Visible = true;
                        pictureBox5.Visible = true;
                        pictureBox6.Visible = true;
                        pictureBox7.Visible = true;
                        pictureBox8.Visible = true;

                        name_label.Text = "";
                        gender_label.Text = "";
                        department_label.Text = "";
                        time_label.Text = "";

                        picFace.Image = null;

                        pictureBox9.Visible = false;
                        pic_retry.Visible = false;
                        pic_retryEn.Visible = false;
                        pictureBox_arTemp.Visible = false;
                    }));

                    ProMemory.IoControllService.YellowOff();
                    ProMemory.IoControllService.GreenOff();
                    ProMemory.IoControllService.RedOff();
                    ProMemory.IoControllService.YellowOn();

                    try
                    {
                        lock (ProMemory.irisConfig.QueueFace)
                        {
                            ProMemory.irisConfig.QueueFace.Clear();
                        }
                        lock (ProMemory.irisConfig.Q2)
                        {
                            ProMemory.irisConfig.Q2.Clear();
                        }
                        lock (ProMemory.irisConfig.Q3)
                        {
                            ProMemory.irisConfig.Q3.Clear();
                        }
                        lock (ProMemory.irisConfig.QueueIdentify)
                        {
                            ProMemory.irisConfig.QueueIdentify.Clear();
                        }
                    }
                    catch (Exception ee)
                    {
                        LogHelper.WriteLog(MethodBase.GetCurrentMethod().DeclaringType, "errorerrorerror ： clear q1/q2/q3/q4 ：" + ee.Message);
                    }

                    ProMemory.irisConfig.IdentifyAccess = false;
                    //ProMemory.findingEyes = false;
                    Thread.Sleep(100);
                    ProMemory.irisConfig.Key_FindEyes = 0;
                    ProMemory.irisConfig.Key_Assess = 0;
                    ProMemory.irisConfig.Key_Identify = 0;

                }
            }
            catch (Exception ex)
            {
                string msg = "init failed!" + ex.Message;
                LogHelper.WriteLog(MethodBase.GetCurrentMethod().DeclaringType, msg);
            }

        }
        /// <summary>
        /// 进入休眠界面
        /// </summary>
        public void ReInitializeToSleep()
        {
            try
            {
                if (this.IsHandleCreated)
                {
                    Invoke(new MethodInvoker(delegate ()
                    {
                        picLive.Visible = true;
                        name_label.Text = "";
                        gender_label.Text = "";
                        department_label.Text = "";
                        time_label.Text = "";
                        pictureBox9.Visible = false;
                        pic_retry.Visible = false;
                        pic_retryEn.Visible = false;
                        pictureBox_arTemp.Visible = false;
                    }));

                    ProMemory.IoControllService.YellowOff();
                    ProMemory.IoControllService.GreenOff();
                    ProMemory.IoControllService.RedOff();
                    try
                    {
                        lock (ProMemory.irisConfig.QueueFace)
                        {
                            ProMemory.irisConfig.QueueFace.Clear();
                        }
                        lock (ProMemory.irisConfig.Q2)
                        {
                            ProMemory.irisConfig.Q2.Clear();
                        }
                        lock (ProMemory.irisConfig.Q3)
                        {
                            ProMemory.irisConfig.Q3.Clear();
                        }
                        lock (ProMemory.irisConfig.QueueIdentify)
                        {
                            ProMemory.irisConfig.QueueIdentify.Clear();
                        }
                    }
                    catch (Exception ee)
                    {
                        LogHelper.WriteLog(MethodBase.GetCurrentMethod().DeclaringType, "errorerrorerror ： clear q1/q2/q3/q4 ：" + ee.Message);
                    }

                    ProMemory.irisConfig.IdentifyAccess = false;
                    // ProMemory.findingEyes = false;

                    Thread.Sleep(100);

                    ProMemory.irisConfig.Key_FindEyes = 0;
                    ProMemory.irisConfig.Key_Assess = 0;
                    ProMemory.irisConfig.Key_Identify = 0;
                    
                }

            }
            catch (Exception ex)
            {
                string msg = "init failed!" + ex.Message;
                LogHelper.WriteLog(MethodBase.GetCurrentMethod().DeclaringType, msg);
            }

        }
        /// <summary>
        /// 识别失败
        /// </summary>
        public void Failure()
        {
            if (ProMemory.isSyning) return;
            try
            {
                Invoke(new MethodInvoker(delegate ()
                {
                    picLive.Visible = false;
                    pictureBox1.Visible = false;
                    pictureBox2.Visible = false;
                    pictureBox3.Visible = false;
                    pictureBox4.Visible = false;
                    pictureBox5.Visible = false;
                    pictureBox6.Visible = false;
                    pictureBox7.Visible = false;
                    pictureBox8.Visible = false;
                    pictureBox_arTemp.Visible = false;
                    picFace.Image = null;
                    
                    if (ProMemory.appConfig.Language == 1)
                    {
                        name_label.Text = "未知人员";
                       pic_retry.Visible = true;
                    }
                    else
                    {
                        name_label.Text = "Unidentified person";
                        pic_retryEn.Visible = true;
                    }

                    gender_label.Text = "";
                    department_label.Text = "";
                    time_label.Text = "";

                    //体温
                    temp_label.Text = ProMemory.tempString.ToString();

                    switch (ProMemory.tempRegion)
                    {
                        case 1:
                            {
                                temp_label.Text = "";
                                temp_text_label.Text = "";
                                if (ProMemory.appConfig.Language == 1)
                                    temp_hl_label.Text = "温度过低，请重试";
                                else
                                {
                                    temp_hl_label.Font = new Font("Times New Roman", 30, FontStyle.Bold);
                                    temp_hl_label.Text = "Too low,retry please";
                                }
                                temp_hl_label.ForeColor = Color.OrangeRed;
                                //PlaySound.recFailureTempLowRetry();
                                break;
                            }
                        case 2:
                            {
                                temp_hl_label.Text = "";

                                if (ProMemory.appConfig.Language == 1) temp_text_label.Text = "体温正常";
                                else
                                {
                                    temp_text_label.Font = new Font("Times New Roman", 24, FontStyle.Bold);
                                    temp_text_label.Text = "Normal";
                                }

                                temp_label.ForeColor = Color.LawnGreen;
                                temp_text_label.ForeColor = Color.LawnGreen;
                                //PlaySound.recFailureTempNormal();
                                break;
                            }
                        case 3:
                            {
                                temp_hl_label.Text = "";
                                if (ProMemory.appConfig.Language == 1)
                                    temp_text_label.Text = "体温异常";
                                else
                                {
                                    temp_text_label.Font = new Font("Times New Roman", 24, FontStyle.Bold);
                                    temp_text_label.Text = "Abnormal";
                                }
                                temp_label.ForeColor = Color.OrangeRed;
                                temp_text_label.ForeColor = Color.OrangeRed;
                                //PlaySound.recFailureTempAbnormal();
                                break;
                            }
                        case 4:
                            {
                                temp_label.Text = "";
                                temp_text_label.Text = "";
                                if (ProMemory.appConfig.Language == 1)
                                    temp_hl_label.Text = "温度过高，请重试";
                                else
                                {
                                    temp_hl_label.Font = new Font("Times New Roman", 30, FontStyle.Bold);
                                    temp_hl_label.Text = "Too high,retry please";
                                }
                                temp_hl_label.ForeColor = Color.OrangeRed;
                                //PlaySound.recFailureTempHighRetry();
                                break;
                            }
                        default: break;
                    }
                    PlaySound.failedRetry();
                }
                ));
                  
                ProMemory.IoControllService.YellowOff();
                ProMemory.IoControllService.RedOn();

            }
            catch (Exception ex)
            {
                LogHelper.WriteErrorLog(MethodBase.GetCurrentMethod().DeclaringType, "failure catch error:  " + ex.Message);
            }
        }

        public void Success(string sPersonId)
        {
            if (ProMemory.isSyning) return;
            long personId = long.Parse(sPersonId);

            DatabaseLocal.OpenDB(ProMemory.appConfig.DbLocalConfig);
            PersonView personView = ProMemory.irisPersonViewService.getPersonViewByPersonIdLocal(personId);

            string name = personView.getName();
            string sex = personView.getSex();
            string deptName = personView.getDeptName();
            string idCardNo = personView.getIdCardNo();
            string photo = personView.getPhoto();
            
            //立思辰打印
            if (ProMemory.appConfig.AuthConfig.HasPrintAuthority)
            {
                PlaySound.recSuccess();
                PrintInterface print = new PrintHelper();
                print.Print(idCardNo, ProMemory.appConfig.AuthConfig.PrintDt.DeviceSN, ProMemory.appConfig.AuthConfig.PrintDt.DestIp,
                    ProMemory.appConfig.AuthConfig.PrintDt.DestPort);


                ProMemory.stringBuilder.Clear();
                ProMemory.stringBuilder.Append("print person：");
                ProMemory.stringBuilder.Append(name);

                LogHelper.WriteInfoLog(MethodBase.GetCurrentMethod().DeclaringType, ProMemory.stringBuilder.ToString());
            }

            Image image = null;
            //下载照片
            image = personView.getPhotoData();
            try
            {
                ProMemory.IoControllService.YellowOff();
                ProMemory.IoControllService.GreenOn();

                DateTime dtNow = DateTime.Now;

                //界面显示
                Invoke(new MethodInvoker(delegate ()
                {
                    name_label.Text = name;
                    gender_label.Text = sex;
                    department_label.Text = deptName;
                    time_label.Text = dtNow.ToString("yyyy-MM-dd HH:mm");

                    //照片
                    if (image != null) picFace.Image = image;

                    //体温
                    temp_label.Text = ProMemory.tempString.ToString();
                    switch (ProMemory.tempRegion)
                    {
                        case 1:
                            {
                                temp_label.Text = "";
                                temp_text_label.Text = "";
                                if (ProMemory.appConfig.Language == 1)
                                    temp_hl_label.Text = "温度过低，请重试";
                                else
                                {
                                    temp_hl_label.Font = new Font("Times New Roman", 30, FontStyle.Bold);
                                    temp_hl_label.Text = "Too low,retry please";
                                }
                                temp_hl_label.ForeColor = Color.OrangeRed;
                                break;
                            }
                        case 2:
                            {
                                temp_hl_label.Text = "";
                                if (ProMemory.appConfig.Language == 1)
                                    temp_text_label.Text = "体温正常";
                                else
                                {
                                    temp_text_label.Font = new Font("Times New Roman", 24, FontStyle.Bold);
                                    temp_text_label.Text = "Normal";
                                }
                                temp_label.ForeColor = Color.LawnGreen;
                                temp_text_label.ForeColor = Color.LawnGreen;
                                break;
                            }
                        case 3:
                            {
                                temp_hl_label.Text = "";
                                if (ProMemory.appConfig.Language == 1)
                                    temp_text_label.Text = "体温异常";
                                else
                                {
                                    temp_text_label.Font = new Font("Times New Roman", 24, FontStyle.Bold);
                                    temp_text_label.Text = "Abnormal";
                                }
                                temp_label.ForeColor = Color.OrangeRed;
                                temp_text_label.ForeColor = Color.OrangeRed;
                                break;
                            }
                        case 4:
                            {
                                temp_label.Text = "";
                                temp_text_label.Text = "";
                                if (ProMemory.appConfig.Language == 1)
                                    temp_hl_label.Text = "温度过高，请重试";
                                else
                                {
                                    temp_hl_label.Font = new Font("Times New Roman", 30, FontStyle.Bold);
                                    temp_hl_label.Text = "Too high,retry please";
                                }
                                temp_hl_label.ForeColor = Color.OrangeRed;
                                break;
                            }
                        default: break;
                    }

                    picLive.Visible = false;
                    pictureBox1.Visible = false;
                    pictureBox2.Visible = false;
                    pictureBox3.Visible = false;
                    pictureBox4.Visible = false;
                    pictureBox5.Visible = false;
                    pictureBox6.Visible = false;
                    pictureBox7.Visible = false;
                    pictureBox8.Visible = false;

                    if (ProMemory.appConfig.TempType == 2)
                        pictureBox_arTemp.Visible = true;
                }
                ));

                //写txt日志
                ProMemory.stringBuilder.Clear();
                ProMemory.stringBuilder.Append(name);
                ProMemory.stringBuilder.Append(",");
                ProMemory.stringBuilder.Append(sex);
                ProMemory.stringBuilder.Append(",");
                ProMemory.stringBuilder.Append(deptName);
                
                string devCode = "";
                string doorCode = "";
                string inoutType = "";

                if (ProMemory.hostIp != "" && ProMemory.hostIp != "127.0.0.1")
                {
                    devCode = ProMemory.irisDeviceService.getDevCode(ProMemory.hostIp);
                    //LogHelper.WriteLog(MethodBase.GetCurrentMethod().DeclaringType, "devCode获取失败");
                }

                //门禁功能
                bool hasPermisson = false;
                if (ProMemory.appConfig.AuthConfig.HasOpenDoorAuthority)
                {
                    hasPermisson = ProMemory.irisPermisionService.GetOpenDoorPermision(ProMemory.appConfig.AuthConfig,
                         personId, devCode, out doorCode, out inoutType);

                    if (hasPermisson &&
                    (!ProMemory.appConfig.AuthConfig.DoorDt.CheckTemp ||
                    (ProMemory.tempRegion == 1 || ProMemory.tempRegion == 2)))
                    {
                        Thread openDoorTh = new Thread(DoorSystem.open);
                        openDoorTh.Start();
                    }
                }
                
                PlaySound.successSound(hasPermisson);

                //考勤
                ProMemory.irisRecordsService.insertRecordsLocal(personId, dtNow, ProMemory.tempString.ToString(),
                        devCode, doorCode, inoutType);

                LogHelper.WriteInfoLog(MethodBase.GetCurrentMethod().DeclaringType, ProMemory.stringBuilder.ToString());
                LogHelper.WriteInfoLog(MethodBase.GetCurrentMethod().DeclaringType, "当前测温："+ProMemory.tempString.ToString());
                
            }
            catch (Exception e)
            {
                LogHelper.WriteErrorLog(MethodBase.GetCurrentMethod().DeclaringType, "success:" + e.Message);
            }
            finally
            {
                if (DatabaseLocal.mySqlConnect.State != ConnectionState.Closed)//本地数据库
                {
                    DatabaseLocal.CloseDB();
                }
            }
        }

        private void tempOcx()
        {
            axMC_DISP1.getTemp();
        }

        //返回温度区间，1-温度过低，2-体温正常，3-体温异常，4-温度过高
        public int obtainTemp()
        {
            int _tempRegion = 0;
            float tempRe = 0;

            float correction = (float)Convert.ToDouble(ConfigHelper.GetAppConfig("correction"));
            float separate0 = (float)Convert.ToDouble(ConfigHelper.GetAppConfig("separate0")) + 30;
            float paramRegion0 = (float)Convert.ToDouble(ConfigHelper.GetAppConfig("paramRegion0"));

            float paramRegion11 = (float)Convert.ToDouble(ConfigHelper.GetAppConfig("paramRegion11"));
            float paramRegion12 = (float)Convert.ToDouble(ConfigHelper.GetAppConfig("paramRegion12"));

            float separate1 = (float)Convert.ToDouble(ConfigHelper.GetAppConfig("separate1")) + 30;

            float paramRegion21 = (float)Convert.ToDouble(ConfigHelper.GetAppConfig("paramRegion21"));
            float paramRegion22 = (float)Convert.ToDouble(ConfigHelper.GetAppConfig("paramRegion22"));

            float paramRegion31 = (float)Convert.ToDouble(ConfigHelper.GetAppConfig("paramRegion31"));
            float paramRegion32 = (float)Convert.ToDouble(ConfigHelper.GetAppConfig("paramRegion32"));

            float separate2 = (float)Convert.ToDouble(ConfigHelper.GetAppConfig("separate2")) + 30;

            float separate3 = (float)Convert.ToDouble(ConfigHelper.GetAppConfig("separate3")) + 30;

            float paramHigh = (float)Convert.ToDouble(ConfigHelper.GetAppConfig("paramHigh"));

            if (ProMemory.appConfig.TempType == 1)
            {
                Thread getTempThread = new Thread(tempOcx);
                getTempThread.Start();
                Thread.Sleep(200);
                tempRe = axMC_DISP1.getTemperature() + correction;
            }
            else
            {
                tempRe = getArTemp() + correction;
            }

            if (tempRe < separate0)
                tempRe = (float)(tempRe + paramRegion0);
            else if (tempRe >= separate0 && tempRe < separate1)
                tempRe = (float)(tempRe * paramRegion11 + paramRegion12);
            else if (tempRe >= separate1 && tempRe < separate2)
                tempRe = (float)(tempRe * paramRegion21 + paramRegion22);
            else if (tempRe >= separate2 && tempRe <= separate3)
                tempRe = (float)(tempRe * paramRegion21 + paramRegion22);
            else if (tempRe > separate3)
                tempRe = tempRe + paramHigh;
            
            float tnor = (float)Convert.ToDouble(ConfigHelper.GetAppConfig("tnor")) + 30;
            float tabnor = (float)Convert.ToDouble(ConfigHelper.GetAppConfig("tabnor")) + 30;

            if (tempRe < 30) {
                Random r = new Random();
                tempRe = r.Next(3580, 3650) / 100.00f;
            }

            //温度结果
            if (tempRe < 30)
                _tempRegion = 1;
            else if (tempRe >= 30 && tempRe <= tnor)
                _tempRegion = 2;
            else if (tempRe > tnor && tempRe <= tabnor)
                _tempRegion = 3;
            else if (tempRe > tabnor)
                _tempRegion = 4;

            ProMemory.tempString.Clear();

            ProMemory.tempString.Append(tempRe.ToString());

            if (tempRe.ToString().Length == 2 || tempRe.ToString().Length == 1)
            {
                ProMemory.tempString.Append(".0℃");
            }
            else if (tempRe.ToString().Length > 3)
            {
                String str = ProMemory.tempString.ToString().Substring(0, 4);
                ProMemory.tempString.Clear();
                ProMemory.tempString.Append(str + "℃");
            }

            return _tempRegion;
        }
        #endregion

        #region 
        Byte[] tempData = new byte[256 * 192 * 2];
        private void showTempPic()
        {
            try
            {
                Init();
                unsafe
                {
                    Byte[] imageData = new byte[256 * 192 * 3];
                    while (true)
                    {
                        //Thread.Sleep(1000);
                        fixed (byte* irisL = &imageData[0])
                        {
                            fixed (byte* irisR = &tempData[0])
                            {
                                byte* ptrIrisL = irisL;
                                byte* ptrIrisR = irisR;
                                ExpData(ref ptrIrisL, ref ptrIrisR);  //质量评估 0均不合格 1一幅合格 2均合格
                            }
                        }

                        Image image = Raw24BitByteArrayToImage(imageData, 192, 256);

                        pictureBox_arTemp.Image = image;
                        pictureBox_arTemp.Refresh();
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private Image Raw24BitByteArrayToImage(byte[] byteArray, int width, int height)
        {

            if ((byteArray == null) || (width <= 0) || (height <= 0))
                return null;

            Bitmap bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb);

            try
            {

                BitmapData bData = bmp.LockBits(new Rectangle(new System.Drawing.Point(), bmp.Size),
                                                ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);


                Marshal.Copy(byteArray, 0, bData.Scan0, byteArray.Length);

                bmp.UnlockBits(bData);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

            return bmp;
        }

        private void GetTempFrame(byte[] byteArray, ref byte[,] tempArray)
        {

            if (byteArray == null)
                return;

            try
            {
                for (int r = 0; r < 192; r++)
                {
                    for (int c = 0; c < 256; c++)
                    {

                        tempArray[c, 192 - 1 - r] = (byte)((byteArray[256 * r + c] + 256 * byteArray[256 * r + c + 1]) / 16 - 273.15);
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

            return;
        }

        public float getArTemp()
        {
            byte[,] tempFrame = new byte[256, 192];
            GetTempFrame(tempData, ref tempFrame);
            Image image = Raw24BitByteArrayToImage(tempData, 192, 256);
            
            Bitmap bitmap = (Bitmap)image;
            Mat mat = BitmapConverter.ToMat(bitmap);

            Rect rect = new Rect(50, 50, 30, 10);
            Cv2.Rectangle(mat, rect, new Scalar(0, 255, 0));

            Mat tpImg = new Mat(mat, rect);

            Scalar meanScalar = Cv2.Mean(tpImg);
            float meanValue = (float)meanScalar.Val0;

            return meanValue;
        }
        #endregion

        private void Form1_KeyUp(object sender, KeyEventArgs e)
        {
            if (Keys.Escape == e.KeyCode)
            {
                // 按键ESC，则退出程序
                LogHelper.WriteWarnLog(MethodBase.GetCurrentMethod().DeclaringType, "按下ESC键，退出");
                System.Environment.Exit(0);
            }
        }
    }
}