using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using AR;
using Project.Class;

namespace Project
{
    public partial class FMain
    {
        public enum EResultKeyence
        {
            Wait = 0,
            Complete,
            TimeOut,
            MultiSID,
            Nothing,
        }
        public EResultKeyence KEYENCE_READ(eWorkPort target, eSMStep cmdIndex)
        {
            UInt16 idx = 1;
            var mv = PUB.Result.vModel;
            var mc = PUB.Result.mModel;
            var funcName = System.Reflection.MethodBase.GetCurrentMethod().Name;
            var seqTime = PUB.sm.seq.GetTime(cmdIndex);
            var msgType = (Class.eStatusMesage)target;
            var itemC = PUB.Result.ItemDataC;
            if (PUB.sm.getNewStep != eSMStep.RUN) return EResultKeyence.Wait;
            //var Jobtype = VAR.STR[eVarString.JOB_TYPE];

            var CVMode = VAR.BOOL[eVarBool.Use_Conveyor];
            var OPT_PrinterOff = PUB.OPT_PRINTEROFF(target);
            var OPT_CameraOff = PUB.OPT_CAMERA();
            var OPT_BYPASS = PUB.OPT_BYPASS();

            //데이터가 완료되었는지 확인
            if (itemC.VisionData.Confirm)
            {
                PUB.log.AddAT("Removing barcode messages due to vision data completion");
                itemC.VisionData.bcdMessage.Clear();
                return EResultKeyence.Complete;
            }

            //사용자 입력 대기중이면 아에 처리하지 않는다 210203
            if (PUB.flag.get(eVarBool.FG_WAIT_LOADERINFO) == true)
            {
                PUB.WaitMessage[1] = "Wait for User Confirm Interface";
                return EResultKeyence.Wait;
            }

            //####################################################
            //###	작업시작
            //####################################################
            if (PUB.sm.seq.Get(cmdIndex) == idx++)
            {
                if (PUB.Result.DryRun)
                {
                    PUB.log.Add($"[{target}] Completed due to DRY-RUN");
                    SetDryrunData();
                }
                else
                {
                    PUB.logDbg.Add($"[{target}] Keyence reading started");
                    if (PUB.keyenceF != null) PUB.keyenceF.Trigger(true);
                    if (PUB.keyenceR != null) PUB.keyenceR.Trigger(true);
                }

                VAR.BOOL[eVarBool.Need_UserConfirm_Data] = false;
                VAR.STR[eVarString.MULTISID_FIELDS] = string.Empty;
                VAR.STR[eVarString.MULTISID_QUERY] = string.Empty;
                VAR.TIME.Update(eVarTime.KEYENCEWAIT);
                PUB.sm.seq.Update(cmdIndex);
                return EResultKeyence.Wait;
            }

            //####################################################
            //###
            //####################################################
            if (PUB.sm.seq.Get(cmdIndex) == idx++)
            {
                //아무것도안함
                PUB.sm.seq.Update(cmdIndex);
                return EResultKeyence.Wait;
            }

            //####################################################
            //###	키엔스데이터를 처리해준다.
            //####################################################
            if (PUB.sm.seq.Get(cmdIndex) == idx++)
            {
                bool vQtyOK = false;
                var vdata = itemC.VisionData;
                //동작중이아니라면 처리하지 않음
                if (PUB.sm.getNewStep != eSMStep.RUN) return EResultKeyence.Wait;

                //바이패스라면 무조건ok한다.
                var systembypassmode = SETTING.Data.SystemBypass;
                if (systembypassmode && PUB.flag.get(eVarBool.FG_RDY_PORT_PC))
                {
                    vdata.SetRID("BP" + DateTime.Now.ToString("yyyyMMddHHmmss"), "bp");
                    vdata.SID = ("100000000");
                    vdata.VNAME = "BYPASS";
                    vdata.MFGDATE = DateTime.Now.ToString("yyyy-MM-dd");
                    vdata.VLOT = "BYPASS";
                    vdata.CUSTCODE = "0000";
                    vdata.CUSTNAME = "BYPASS";
                    vdata.QTY = "10000";
                    vdata.ConfirmUser = true;
                    vdata.PrintPositionData = "1";
                    vdata.PrintPositionCheck = true;
                    vdata.MFGDATE_Trust = true;
                    vdata.PARTNO_Trust = true;
                    vdata.QTY_Trust = true;
                    vdata.RID_Trust = true;
                    vdata.SID_Trust = true;
                    vdata.VLOT_Trust = true;
                    vdata.VNAME_Trust = true;
                    return EResultKeyence.Complete;
                }

                //로더정보를 사용자가 처리중이면 동작 안함
                if (VAR.BOOL[eVarBool.FG_WAIT_LOADERINFO]) return EResultKeyence.TimeOut;

                //다중SID환경에서 데이터를 선택하고 있다.
                if (VAR.BOOL[eVarBool.FG_WAIT_INFOSELECT]) return EResultKeyence.Wait;

                //데이터 처리 시간을 넘어서면 사용자 확인 창을 띄운다 220621
                var ts = VAR.TIME.RUN((int)eVarTime.KEYENCEWAIT);
                if (VAR.BOOL[eVarBool.FG_RDY_PORT_PC] && ts.TotalMilliseconds > AR.SETTING.Data.Timeout_VisionProcessL)
                {
                    //화면업데이트를 종료한다
                    if (PUB.keyenceF != null) PUB.keyenceF.Trigger(false);
                    if (PUB.keyenceR != null) PUB.keyenceR.Trigger(false);

                    //이미지저장용 작업시작
                    var tempfileF = System.IO.Path.Combine(UTIL.CurrentPath, "Temp", "Image", DateTime.Now.ToString("yyyMMddHhmmss_fff" + "F.bmp"));
                    var tempfileR = System.IO.Path.Combine(UTIL.CurrentPath, "Temp", "Image", DateTime.Now.ToString("yyyMMddHhmmss_fff" + "R.bmp"));
                    var tempfiF = new System.IO.FileInfo(tempfileF);
                    var tempfiR = new System.IO.FileInfo(tempfileR);
                    if (tempfiF.Directory.Exists == false) tempfiF.Directory.Create();
                    if (tempfiR.Directory.Exists == false) tempfiR.Directory.Create();

                    //마지막 사진을 추출한다
                    var CurImageF = PUB.keyenceF.SaveImage(tempfiF.FullName);
                    var CurImageR = false;
                    if (PUB.keyenceR != null) CurImageR = PUB.keyenceR.SaveImage(tempfiR.FullName);
                  
                    PUB.keyenceF.Trigger(true);
                    PUB.keyenceR.Trigger(true);
                    return EResultKeyence.TimeOut;
                }


                var prcResult = BCDProcess_ALL(itemC, "SEQ", true);
                if (prcResult != EResultKeyence.Nothing)
                    return prcResult;

                PUB.sm.seq.Update(cmdIndex);
                return EResultKeyence.Wait;
            }

            //####################################################
            //###	
            //####################################################
            if (PUB.sm.seq.Get(cmdIndex) == idx++)
            {
                PUB.sm.seq.Update(cmdIndex);
                return EResultKeyence.Wait;
            }

            PUB.sm.seq.Clear(cmdIndex);
            return EResultKeyence.Complete;
        }

        /// <summary>
        /// 데이터입력이 완료되었는지 확인 합니다
        /// </summary>
        /// <param name="item"></param>
        /// <param name="Source"></param>
        /// <param name="mainjob"></param>
        void CheckDataComplte(Class.JobData item, string Source, bool mainjob)
        {
            Boolean NeedConfirm = false;
            //var Jobtype = VAR.STR[eVarString.JOB_TYPE];
            var OPT_BYPASS = SETTING.Data.SystemBypass;// Jobtype == "BP";
            var CVMode = VAR.BOOL[eVarBool.Use_Conveyor];
            var CustomerCode = VAR.STR[eVarString.JOB_CUSTOMER_CODE];
            if (item.VisionData.Confirm)
            {
                //사용자에의해 완성된 자료는 완료된 자료이다
                if (item.VisionData.bcdMessage.Count > 0) item.VisionData.bcdMessage.Clear();
                return;
            }

            //처음작업이면 반드시 확인을 한다
            if (OPT_BYPASS == false && PUB.Result.JobFirst)
            {
                //사용자확인이 필요없는 상태라면 활성화해준다
                //프린트를 하지 않는다면 처리하지 않는다.
                if (VAR.BOOL[eVarBool.Opt_DisablePrinter] == false)
                {
                    if (mainjob && item.VisionData.bcdMessage.ContainsKey(6) == false) item.VisionData.bcdMessage.Add(6, "First reel confirmation required");
                    NeedConfirm = true;
                }
            }

            //서버의수량업데이트기능
            if (OPT_BYPASS == false && VAR.BOOL[eVarBool.Opt_ServerQty])
            {
                //수량원본이 없는 경우
                if (item.VisionData.QTY0.isEmpty())
                {
                    string msg = "Server quantity update feature is not applicable to WMS, contact developer if needed";
                    var cnt = 0;// (int)(Amkor.RestfulService.get_stock_count(item.VisionData.RID, out msg));
                    if (mainjob)
                    {
                        PUB.log.AddE("Server quantity update feature is not applicable to WMS, contact developer if needed");
                    }
                    if (cnt > 0)
                    {
                        //새로받은 데이터를 실제 수량에 추가한다
                        item.VisionData.QTY0 = item.VisionData.QTY;
                        item.VisionData.QTY = cnt.ToString();
                        if (mainjob) PUB.log.Add($"Server quantity update RID:{item.VisionData.RID} Old:{item.VisionData.QTY}, New:{cnt}");
                    }
                    else
                    {
                        if (mainjob) PUB.log.AddE($"Quantity update failed rID:{item.VisionData.RID}, Message={msg}");
                        NeedConfirm = true;
                        if (mainjob && item.VisionData.bcdMessage.ContainsKey(1) == false)
                            item.VisionData.bcdMessage.Add(1, "Quantity update failed");
                    }
                }
            }

            //수량입력 210708
            if (OPT_BYPASS == false && VAR.BOOL[eVarBool.Opt_UserQtyRQ])
            {
                if (item.VisionData.QTYRQ && item.VisionData.QTY.isEmpty() == false)
                {
                    //RQ값이 이전 값이 오기도 하니 바코드 목록에서 값을 다시 써준다. 210825
                    var rqBcd = PUB.Result.ItemDataC.VisionData.barcodelist.Where(t => t.Value.Data.StartsWith("RQ")).FirstOrDefault();
                    if (rqBcd.Value != null)
                    {
                        var newqty = rqBcd.Value.Data.Substring(2).Trim();
                        if (mainjob) PUB.log.Add($"Quantity update (01) {item.VisionData.QTY}->{newqty}");
                        item.VisionData.QTY = newqty;
                        if (mainjob) PUB.log.AddI("Manual quantity input mode but RQ value confirmed, no user confirmation required");
                    }
                    else
                    {
                        if (mainjob && item.VisionData.bcdMessage.ContainsKey(2) == false) item.VisionData.bcdMessage.Add(2, "RQ value error (auto mode not possible)");
                        NeedConfirm = true;
                    }
                }
                else
                {
                    if (mainjob && item.VisionData.bcdMessage.ContainsKey(3) == false) item.VisionData.bcdMessage.Add(3, "Manual quantity input required");
                    NeedConfirm = true;
                }
            }


            //프린트위치확인
            BCDProcess_BCDPrint(item);
            if (item.VisionData.PrintPositionData.isEmpty() == true || item.VisionData.PrintPositionCheck == false)
            {
                if (mainjob && item.VisionData.bcdMessage.ContainsKey(4) == false) item.VisionData.bcdMessage.Add(4, "Attachment position not found");
                NeedConfirm = true;
            }

            //SID 존재여부 확인
            if (OPT_BYPASS == false && item.VisionData.SID_Trust && VAR.BOOL[eVarBool.Opt_CheckSIDExist])
            {
                //ECS목록에 데이터가 업다면 오류로 처리한다
                var SID = item.VisionData.SID;
                var ta = new DataSet1TableAdapters.QueriesTableAdapter();
                var exist = ta.CheckSIDExist(SID) > 0;
                PUB.log.Add($"SID Exist Check SID:{item.VisionData.SID},Result={exist}");
                if (exist == false)
                {
                    PUB.Result.SetResultMessage(eResult.OPERATION, eECode.NOSIDINFOFROMDB, eNextStep.PAUSE, SID);
                    return;
                }
            }

            //sid변환기능확인
            var SIDOK = false;
            if (OPT_BYPASS == false &&
                VAR.BOOL[eVarBool.Opt_SIDConvert] &&
                PUB.flag.get(eVarBool.FG_WAIT_LOADERINFO) == false &&
                VAR.BOOL[eVarBool.JOB_Empty_SIDConvertInfo] == false)
            {
                //시드값이 유효한지 확인한다.
                SIDOK = item.VisionData.SID_Trust && item.VisionData.SID0.isEmpty() == false && item.VisionData.SID.isEmpty() == false;
            }
            else SIDOK = (item.VisionData.SID_Trust && item.VisionData.SID.isEmpty() == false); //시드변환을 사용하지 않으므로 시드값여부에따라 다르다

            //수량확인
            if (OPT_BYPASS == false)
            {
                if(double.TryParse(item.VisionData.QTY,out double qtyvalue)==false)
                {
                    if (mainjob && item.VisionData.bcdMessage.ContainsKey(8) == false) item.VisionData.bcdMessage.Add(8, "Qty invalid");
                    NeedConfirm = true;
                }
            }


            //사용자확인이 필요한 옵션이라면 사용한다
            if (OPT_BYPASS == false && VAR.BOOL[eVarBool.Opt_UserConfim])
            {
                if (mainjob && item.VisionData.bcdMessage.ContainsKey(5) == false) item.VisionData.bcdMessage.Add(5, "User confirmation required");
                NeedConfirm = true;
            }




            //변환작업인데 원본 값이 없다.
            //혹은 변환값과 원본이 같다
            if (OPT_BYPASS == false && VAR.BOOL[eVarBool.Opt_SIDConvert] && (item.VisionData.SID0.isEmpty() == true || item.VisionData.SID0 == item.VisionData.SID))
            {
                if (mainjob && item.VisionData.bcdMessage.ContainsKey(7) == false) item.VisionData.bcdMessage.Add(7, "SID conversion value confirmation required");
                NeedConfirm = true;
            }

            //데이터의 신뢰성을 확인하고 모두 입력되었다면 자동 확정을 진행한다
            if (item.VisionData.MFGDATE_Trust &&
                item.VisionData.PARTNO_Trust &&
                item.VisionData.QTY_Trust &&
                item.VisionData.RID_Trust &&
                item.VisionData.SID_Trust &&
                SIDOK && item.VisionData.VLOT_Trust &&
                item.VisionData.VNAME_Trust)
            {
                //데이터를 확정짓는다 다만 화면을 표시하지 않아야하는 경우에만 처리해준다
                if (NeedConfirm == false)
                {
                    if (OPT_BYPASS)
                    {
                        PUB.log.Add("All data confirmed, proceeding with automatic confirmation (bypass mode)");
                        if (item.VisionData.bcdMessage.Count > 0) item.VisionData.bcdMessage.Clear();
                        item.VisionData.ConfirmBypass = true;
                    }
                    else if (item.VisionData.ConfirmAuto == false)
                    {
                        PUB.log.Add("All data confirmed, proceeding with automatic confirmation");
                        if (item.VisionData.bcdMessage.Count > 0) item.VisionData.bcdMessage.Clear();
                        item.VisionData.ConfirmAuto = true;
                    }
                }
            }
            else if (item.VisionData.QRInputRaw.isEmpty() == false)
            {
                if (mainjob)
                {
                    NeedConfirm = true;
                    PUB.log.AddAT($"Data incomplete but QR has been read, showing confirmation window immediately");
                }
            }

            //확인창을 띄우기 위해 Timeout 오류를 발생시킨다.
            VAR.BOOL[eVarBool.Need_UserConfirm_Data] = NeedConfirm;
            if (NeedConfirm)
            {
                if (mainjob)
                {
                    var newtime = DateTime.Now.AddMilliseconds(-AR.SETTING.Data.Timeout_VisionProcessL);
                    VAR.TIME.Set(eVarTime.KEYENCEWAIT, newtime);
                }
            }
            else if (PUB.Result.ItemDataC.VisionData.ConfirmAuto == false)
            {
                PUB.logDbg.Add($"Vision automatic confirmation processing {Source}");
                PUB.Result.ItemDataC.VisionData.ConfirmAuto = true;
            }

        }

        List<string> warninactivelist = new List<string>();
        private void SetDryrunData()
        {
            var item = PUB.Result.ItemDataC;
            PUB.log.AddAT("Dry run basic data input");
            if (item.VisionData.QTY.isEmpty()) item.VisionData.QTY = DateTime.Now.ToString("HHmm");
            if (item.VisionData.MFGDATE.isEmpty()) item.VisionData.MFGDATE = DateTime.Now.ToString("yy-MM-dd");
            if (item.VisionData.SID.isEmpty()) item.VisionData.SID = "108" + "0" + DateTime.Now.ToString("HH").PadLeft(2, '0') + DateTime.Now.ToString("fff").PadLeft(3, '0');
            if (item.VisionData.VLOT.isEmpty()) item.VisionData.VLOT = "SUPNAME" + DateTime.Now.ToString("fff");
            if (item.VisionData.PARTNO.isEmpty()) item.VisionData.PARTNO = "PARTNO" + DateTime.Now.ToString("yyyyMMddHHmmss.fff");
            if (item.VisionData.RID.isEmpty())
            {
                var newid = PUB.MakeNewREELID(item.VisionData.SID);// Amkor.RestfulService.Allocation_Unique_ReelID_AmkorSTD("1234", "4", "A", out string err);
                if (newid.success == false) item.VisionData.SetRID("RID" + DateTime.Now.ToString("yyyyMMddHHmmss.fff"), "DRY");
                else item.VisionData.SetRID(newid.newid, "DRY");
            }
            if (item.VisionData.PrintPositionData.isEmpty()) item.VisionData.PrintPositionData = "2";
            item.VisionData.PrintPositionCheck = true;
            item.VisionData.ConfirmAuto = true;
        }
    }
}