using irisHelper;
using irisRefactor.FrmService;
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;

namespace irisRefactor.IrisThread
{
    /**
     * 识别之前的线程
     * 找眼和质量评估两步操作串行进行
     * 
     */    
    class PreIdentifyTh
    {
        private PreIdentifyTh() { }

        private static readonly PreIdentifyTh preIdentifyTh = new PreIdentifyTh();
        
        public static PreIdentifyTh GetInstance { get => preIdentifyTh; }

        public void FindEyes()
        {
            LogHelper.WriteInfoLog(MethodBase.GetCurrentMethod().DeclaringType, "PreIdentify Thread Started");

            // 用于计算操作耗时
            Stopwatch sw = new Stopwatch();

            // 线程启动后，一直在运行中
            while (true)
            {
                // 没有在休眠中；没有数据同步中
                if (ProMemory.isWait == false && ProMemory.isSyning == false && 
                    ProMemory.identifyConfig.FlagFindingEye == true)
                {
                    // 取出来图像
                    if (ProMemory.irisConfig.QueueFace.Count > 0)
                    {
                        lock (ProMemory.irisConfig.QueueFace)
                        {
                            if (ProMemory.irisConfig.QueueFace.Count > 0)
                            {
                                ProMemory.irisConfig.FaceBuffer = ProMemory.irisConfig.QueueFace.Pop();
                            }
                        }

                        int eyeCount = 0;
                        int[] irisPos = new int[6];
                        if (ProMemory.irisConfig.FaceBuffer != null)
                        {
                            // 执行找眼
                            sw.Restart();
                            eyeCount = this.ExeCaptureEye(ref irisPos);
                            sw.Stop();
                            LogHelper.WriteDebugLog(MethodBase.GetCurrentMethod().DeclaringType, "找眼[" + eyeCount + "个][耗时" + sw.ElapsedMilliseconds + "ms]");
                        }

                        if (eyeCount > 0) // 找到一个或者两个眼睛
                        {
                            if (ProMemory.identifyConfig.IdentifyTaskId == "") // 不在识别过程中
                            {
                                // 启动一次识别过程
                                // 1.设置id
                                ProMemory.identifyConfig.StartIdentify(DateTime.Now.ToString("yyyyMMddHHmmssfff"), DateTime.Now.Ticks / 10000);

                                // 启动识别线程
                                // ProMemory.irisConfig.IdentifyThreadRun = true;
                                Thread identifyThread = new Thread(IdentifyTh.GetInstance.Identify)
                                {
                                    Name = "Identify Thread" + DateTime.Now.ToString("[MMddHHmmss]")
                                };
                                identifyThread.Start();

                                //黄灯闪烁
                                ProMemory.IoControllService.setYellowFlash(true);
                                Thread flashThrd = new Thread(ProMemory.IoControllService.YellowFlash);
                                flashThrd.Start();

                            }
                            else // 在识别过程中，继续评估，并将合格图像存入堆栈
                            {
                                ProMemory.identifyConfig.CountTryIdentify++; // ★尝试识别计数器+1

                                if (ProMemory.identifyConfig.CountTryIdentify > Convert.ToInt32(ConfigHelper.GetAppConfig("maxTryIdentify"))) // ★连续20次尝试未识别成功则识别失败
                                {
                                    if (ProMemory.appConfig.AuthConfig.HasTempDtAuthority)
                                    {
                                        ProMemory.tempRegion = Form1.GetInstance().obtainTemp();
                                        LogHelper.WriteInfoLog(MethodBase.GetCurrentMethod().DeclaringType, "未知人员温度:" + ProMemory.tempString.ToString());
                                    }

                                    LogHelper.WriteInfoLog(MethodBase.GetCurrentMethod().DeclaringType, "识别超时[" + ProMemory.identifyConfig.IdentifyTaskId + "]");

                                    // 判断是否已经识别成功了
                                    if (ProMemory.identifyConfig.IdentifyStart != 0)
                                    {
                                    if (ProMemory.formType == "1")
                                            Form1.GetInstance().Failure();
                                        else if (ProMemory.formType == "2")
                                            Form2.GetInstance().Failure();
                                        Thread.Sleep(ProMemory.appConfig.ShowTimeFailure);
                                    }

                                    // 将变量清零
                                    ProMemory.identifyConfig.InitConfig();
                                }
                            }

                            // 调用质量评估方法
                            Byte[] irisBytesL = new byte[640 * 480];
                            Byte[] irisBytesR = new byte[640 * 480];

                            sw.Restart();
                            int score = this.ExeAssessFocus(irisPos, ref irisBytesL, ref irisBytesR);
                            sw.Stop();
                            LogHelper.WriteDebugLog(MethodBase.GetCurrentMethod().DeclaringType, "质量评估[" + score + "个][耗时" + sw.ElapsedMilliseconds + "ms]");

                            if (score == 1)
                            {
                                lock (ProMemory.irisConfig.QueueIdentify)
                                {
                                    ProMemory.irisConfig.QueueIdentify.Push(irisBytesL);
                                }
                            }
                            else if (score == 2)
                            {
                                lock (ProMemory.irisConfig.QueueIdentify)
                                {
                                    ProMemory.irisConfig.QueueIdentify.Push(irisBytesL);
                                    ProMemory.irisConfig.QueueIdentify.Push(irisBytesR);
                                }
                            }
                        }
                        else // 没找到眼
                        {
                            if (ProMemory.identifyConfig.IdentifyTaskId == "") // 不在识别过程中
                            {
                                ProMemory.identifyConfig.CountNoEyeLast++; // ★持续未找到眼计数器+1
                                
                                if (ProMemory.identifyConfig.CountNoEyeLast > Convert.ToInt32(ConfigHelper.GetAppConfig("maxCountNoEyeLast"))) // ★连续200张图片未找到眼则待机
                                {
                                    LogHelper.WriteDebugLog(MethodBase.GetCurrentMethod().DeclaringType, "准备待机[" + ProMemory.identifyConfig.CountNoEyeLast + "][" + ProMemory.m_bGrabbing + "]");
                                    ProMemory.identifyConfig.CountNoEyeLast = 0; // ★将持续未找到眼的控制变量清零
                                    if (ProMemory.m_bGrabbing)
                                    {
                                        if (ProMemory.IoControllService.getSensorVal() == 0) //未再次触发,待机
                                        {
                                            if (ProMemory.formType == "1")
                                                Form1.GetInstance().ReInitializeToSleep();
                                            else if (ProMemory.formType == "2")
                                                Form2.GetInstance().ReInitializeToSleep();
                                            Thread.Sleep(200);
                                            ProMemory.cameraController.ContinuousShot_TriggerOn();
                                        }
                                        else //已再次触发,继续下一轮识别
                                        {
                                            ProMemory.cameraController.ContinuousShot_TriggerOff();
                                        }
                                    }
                                }
                            }
                            else // 在某次识别过程中，
                            {
                                ProMemory.identifyConfig.CountTryIdentify++; // ★尝试识别计数器+1

                                if (ProMemory.identifyConfig.CountTryIdentify > Convert.ToInt32(ConfigHelper.GetAppConfig("maxTryIdentify"))) // ★连续20次尝试未识别成功则识别失败
                                {
                                    if (ProMemory.appConfig.AuthConfig.HasTempDtAuthority)
                                    {
                                        ProMemory.tempRegion = Form1.GetInstance().obtainTemp();
                                        LogHelper.WriteInfoLog(MethodBase.GetCurrentMethod().DeclaringType, "未知人员温度:" + ProMemory.tempString.ToString());
                                    }

                                    LogHelper.WriteInfoLog(MethodBase.GetCurrentMethod().DeclaringType, "识别超时[" + ProMemory.identifyConfig.IdentifyTaskId + "]");

                                    // 判断是否已经识别成功了
                                    if (ProMemory.identifyConfig.IdentifyStart != 0)
                                    {
                                        if (ProMemory.formType == "1")
                                            Form1.GetInstance().Failure();
                                        else if (ProMemory.formType == "2")
                                            Form2.GetInstance().Failure();
                                        Thread.Sleep(ProMemory.appConfig.ShowTimeFailure);
                                    }

                                    // 将变量清零
                                    ProMemory.identifyConfig.InitConfig();
                                }
                            }
                        }
                    }
                    else
                    {
                        // 堆栈中没有图像则跳过
                        continue;
                    }
                }
            }
        }

        /**
         * 调用找眼方法
         * 返回找到的眼睛数
         */
        private int ExeCaptureEye(ref int[] irisPos)
        {
            unsafe
            {
                IntPtr ptrFace = Marshal.AllocHGlobal(1280 * 960);
                Marshal.Copy(ProMemory.irisConfig.FaceBuffer, 0, ptrFace, 1280 * 960);

                int mark = 0;
                int[] posvec = new int[] { 0, 0, 0, 0, 0, 0 };

                fixed (int* pos = &posvec[0])
                {
                    int* ptrPos = pos;
                    mark = ProMemory.CaptureEye_Rec(ptrFace, ref ptrPos);
                    for (int i = 0; i < irisPos.Length; i++)
                    {
                        irisPos[i] = ptrPos[i];
                    }
                }

                Marshal.FreeHGlobal(ptrFace);

                // 返回找到的眼睛数
                return mark;
            }
        }

        private int ExeAssessFocus(int[] irisPos, ref byte[] irisBytesL, ref byte[] irisBytesR)
        {
            int score = 0;

            if (ProMemory.irisConfig.FaceBuffer != null)
            {
                IntPtr ptrIrisFace = Marshal.AllocHGlobal(1280 * 960);
                Marshal.Copy(ProMemory.irisConfig.FaceBuffer, 0, ptrIrisFace, 1280 * 960);
                unsafe
                {
                    fixed (byte* irisL = &irisBytesL[0])
                    {
                        fixed (byte* irisR = &irisBytesR[0])
                        {
                            byte* ptrIrisL = irisL;
                            byte* ptrIrisR = irisR;
                            score = ProMemory.AssessFocus_Rec(ptrIrisFace, irisPos, ref ptrIrisL, ref ptrIrisR);  //质量评估 0均不合格 1一幅合格 2均合格
                        }
                    }
                }

                Marshal.FreeHGlobal(ptrIrisFace);
            }


            return score;
        }
    }
}
