using Emgu.CV.Structure;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Collections.Concurrent;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using AR;

namespace Project.Class
{
    public class VisionData : INotifyPropertyChanged
    {
        public int RetryLoader { get; set; }
        public List<string> bcdMessage { get; set; }
        public Boolean LightOn { get; set; }
        public DateTime STime;      //비젼시작시간
        public DateTime ETime;      //비젼종료시간
        public TimeSpan RunTime { get { return ETime - STime; } }   //비젼동작시간
        public DateTime GTime;      //이미지수집시간
        public string FileNameL;    //로딩존 촬영
        public string FileNameU;    //언로딩존 촬영
        public Boolean Complete;

        public override string ToString()
        {
            var sb = new StringBuilder();
            sb.AppendLine($"SID:{SID}:{(SID_Trust ? "O" : "X")}");
            sb.AppendLine($"RID:{RID}:{(RID_Trust ? "O" : "X")}");
            sb.AppendLine($"LOT:{VLOT}:{(VLOT_Trust ? "O" : "X")}");
            sb.AppendLine($"QTY:{QTY}:{(QTY_Trust ? "O" : "X")}");
            sb.AppendLine($"BAT:{BATCH}");
            sb.AppendLine($"MFG:{MFGDATE}:{(MFGDATE_Trust ? "O" : "X")}");
            sb.AppendLine($"CPN:{PARTNO}:{(PARTNO_Trust ? "O" : "X")}");

            sb.AppendLine($"RID2:{RID2}");
            sb.AppendLine($"RIDNew:{RIDNew}");
            sb.AppendLine($"SID0:{SID0}");
            return sb.ToString();
        }
        //public Boolean AngleQR { get; set; }
        //public Boolean AngleSTD { get; set; }
        //public double Angle { get; set; }

        //public Boolean IsAngleSet
        //{
        //    get
        //    {
        //        if (AngleQR == false && AngleSTD == false && Angle == 0.0) return true;
        //        else return false;
        //    }
        //}

        /// <summary>
        /// 부착위치에따른 추가회전
        /// </summary>
        public double PositionAngle { get; set; }
        public double ApplyAngle { get; set; }     //적용된 회전 각도
        public Boolean NeedCylinderForward { get; set; } //부착시 실린더를 올려야하는가
        public Boolean ApplyOffset { get; set; }
        public Boolean BaseAngle(out string msg, out KeyenceBarcodeData bcd)
        {

            msg = string.Empty;
            bcd = null;

            //데이터없다면 회전하지 못한다.
            if (this.barcodelist == null || this.barcodelist.Count < 1)
            {
                msg = "No barcode data";
                return false;
            }

            //사용자가 확정한 코드를 우선으로 한다
            KeyValuePair<string, Class.KeyenceBarcodeData> bcddata;

            var bcdCanList = barcodelist.Where(t => t.Value.Ignore == false).ToList();
            bcddata = bcdCanList.Where(t => t.Value.UserActive).FirstOrDefault();
            if (bcddata.Value != null)
            {
                bcd = bcddata.Value;
                msg = "User Active";
                return true;
            }

            //표준바코드를 최우선 으로 사용
            //15자리 기존 바코드는 angle 로 사용하지 않는다.
            //이것은 각도가 일정치 않게 붙어지기 때문이다
            bcddata = bcdCanList.Where(t => t.Value.isSTDBarcode && t.Value.isNewLen15 == false).FirstOrDefault();
            if (bcddata.Value != null)
            {
                bcd = bcddata.Value;
                msg = "STD Barcode";
                return true;
            }

            //QR코드를 우선으로 사용 - return 릴은 적용하지 안게한다.
            //RQ코드가 적용되지 않게한다  210824
            bcddata = bcdCanList.Where(t => t.Value.barcodeSymbol == "1" && t.Value.isNewLen15 == false && t.Value.Data.EndsWith(";;;") == false && t.Value.Data.StartsWith("RQ") == false).FirstOrDefault();
            if (bcddata.Value != null)
            {
                bcd = bcddata.Value;
                msg = "QR Code";
                return true;
            }

            //datamatrix, pdf417
            bcddata = bcdCanList.Where(t => t.Value.barcodeSymbol != "11" && t.Value.barcodeSymbol != "6" && t.Value.Data.StartsWith("RQ") == false).FirstOrDefault();
            if (bcddata.Value != null)
            {
                bcd = bcddata.Value;
                return true;
            }

            //첫번쨰 아이템을 우선으로 사용
            if (bcdCanList.Count == 1)
            {
                bcd = bcdCanList.First().Value;
                msg = "Only One Barcode = " + bcd.Data;
                return true;
            }
            else if (bcdCanList.Count > 1)
            {
                //여러개가 있음
                bcddata = bcdCanList.Where(t => t.Value.barcodeSymbol == "0").FirstOrDefault();
                if (bcd != null)
                {
                    bcd = bcddata.Value;
                    msg = "1D Data";
                    return true;
                }
                else
                {
                    bcd = bcdCanList.First().Value;//[0];
                    msg = $"first({bcd.barcodeSymbol}:{bcd.Data})";
                    return true;
                }
            }
            else
            {
                bcd = null;
                msg = "no data";
                return false;
            }

            // angle = bcd.Angle;
            //return true;
        }   //모션회전각도
        public Boolean Ready { get; set; }
        public Boolean ServerUpdate { get; set; }

        public Boolean Confirm
        {
            get
            {
                return ConfirmAuto || ConfirmUser || ConfirmBypass;
            }
        }
        public Boolean ConfirmUser { get; set; }
        public Boolean ConfirmAuto { get; set; }
        public bool ConfirmBypass { get; set; }

        public Boolean ValidSkipbyUser { get; set; }

        private string _rid = string.Empty;
        private string _qty = string.Empty;
        private string _qty0 = string.Empty;
        private string _sid0 = string.Empty;
        private string _sid = string.Empty;
        private string _rid0 = string.Empty;
        private string _vlot = string.Empty;
        private string _vname = string.Empty;
        private string _mfgdate = string.Empty;
        private string _partno = string.Empty;
        private string _custcode = string.Empty;
        private string _custname = string.Empty;
        private string _batch = string.Empty;
        private string _qtymax = string.Empty;
        private string _mcn = string.Empty;

        public bool SID_Trust { get; set; }
        public bool RID_Trust { get; set; }
        public bool VLOT_Trust { get; set; }
        public bool MFGDATE_Trust { get; set; }
        public bool QTY_Trust { get; set; }
        public bool PARTNO_Trust { get; set; }
        public bool VNAME_Trust { get; set; }
        public string Target { get; set; }

        public string MCN
        {
            get { return _mcn; }
            set { _mcn = value; OnPropertyChanged(); }
        }


        /// <summary>
        /// Original QTY
        /// </summary>
        public string QTY0
        {
            get { return _qty0; }
            set { _qty0 = value; OnPropertyChanged(); }
        }

        /// <summary>
        /// Qty
        /// </summary>
        public string QTY
        {
            get { return _qty; }
            set { _qty = value; OnPropertyChanged(); }
        }

        /// <summary>
        /// QTY값이 RQ에서 입력된 데이터인가?
        /// </summary>
        public Boolean QTYRQ { get; set; }

        public string RID0
        {
            get { return _rid0; }
            set { _rid0 = value; OnPropertyChanged(); }
        }
        public string VLOT
        {
            get { return _vlot; }
            set { _vlot = value; OnPropertyChanged(); }
        }
        public string VNAME
        {
            get { return _vname; }
            set { _vname = value; OnPropertyChanged(); }
        }
        public string MFGDATE
        {
            get { return _mfgdate; }
            set { _mfgdate = value; OnPropertyChanged(); }
        }
        public string PARTNO
        {
            get { return _partno; }
            set { _partno = value; OnPropertyChanged(); }
        }


        /// <summary>
        /// Original SID
        /// </summary>
        public string SID0
        {
            get { return _sid0; }
            set { _sid0 = value; OnPropertyChanged(); }
        }

        public string BATCH
        {
            get
            {
                return _batch;
            }
            set
            {
                _batch = value; OnPropertyChanged();
            }
        }

        public string QTYMAX
        {
            get
            {
                return _qtymax;
            }
            set
            {
                _qtymax = value; OnPropertyChanged();
            }
        }


        public string SID
        {
            get { return _sid; }
            set { _sid = value; OnPropertyChanged(); }
        }

        private void OnPropertyChanged([CallerMemberName] string caller = "")
        {
            PropertyChanged?.Invoke(this,
                new PropertyChangedEventArgs(caller));
        }


        /// <summary>
        /// Reel ID
        /// </summary>
        public string RID
        {
            get { return _rid; }
            private set { _rid = value; OnPropertyChanged(); }
        }

        /// <summary>
        /// 릴 ID를 설정합니다.trust 상태를 자동으로 true 값으로 전환합니다
        /// </summary>
        /// <param name="value"></param>
        /// <param name="reason"></param>
        public void SetRID(string value, string reason)
        {
            //값이 변경될때 로그에 변경
            if (_rid.Equals(value) == false)
            {
                PUB.AddDebugLog(string.Format("RID Changed {0} -> {1} by {2}", _rid, value, reason));
            }
            RID = value;
            RID_Trust = true;
        }

        public Boolean RIDNew { get; set; }
        public Boolean HASHEADER { get; set; }



        public string CUSTCODE
        {
            get { return _custcode; }
            set { _custcode = value; OnPropertyChanged(); }
        }
        public string CUSTNAME
        {
            get { return _custname; }
            set { _custname = value; OnPropertyChanged(); }
        }

        /// <summary>
        /// 데이터가 모두존재하는지 확인
        /// </summary>
        public Boolean DataValid
        {
            get
            {
                if (Confirm == false) return false;
                return QTY.isEmpty() == false &&
                    SID.isEmpty() == false &&
                    RID.isEmpty() == false &&
                    VLOT.isEmpty() == false &&
                    VNAME.isEmpty() == false &&
                    MFGDATE.isEmpty() == false &&
                    PARTNO.isEmpty();
            }
        }


        public Boolean PrintPositionCheck { get; set; }
        public string PrintPositionData { get; set; }

        //상단위치에 프린트를 할것인가?
        //프린트위치에 따른다
        public ePrintPutPos GetPrintPutPosition()
        {
            //하단에 찍는경우이다
            if (PrintPositionData == "1" ||
                PrintPositionData == "2" ||
                PrintPositionData == "3")
            {
                return ePrintPutPos.Bottom;
            }
            else if (PrintPositionData == "7" ||
                PrintPositionData == "8" ||
                PrintPositionData == "9")
            {
                return ePrintPutPos.Top;
            }
            else if (PrintPositionData == "4")  //왼쪽
            {
                if (ReelSize == eCartSize.Inch7)
                    return ePrintPutPos.Top;
                else
                    return ePrintPutPos.Middle;
            }
            else if (PrintPositionData == "6")  //오른쪽
            {
                if (ReelSize == eCartSize.Inch7)
                    return ePrintPutPos.Top;
                else
                    return ePrintPutPos.Middle;
            }
            else return ePrintPutPos.None;

        }
        //public string LabelPos { get; set; }
        //public Boolean PrintForce { get; set; }

        public eCartSize ReelSize { get; set; }

        public string QTY2 { get; set; }       //바코드수량
        public string SID2 { get; set; }     //바코드
        public string RID2 { get; set; }     //바코드        
        public string VLOT2 { get; set; }
        public string VNAME2 { get; set; }
        public string MFGDATE2 { get; set; }
        public string PARTNO2 { get; set; }

        public Emgu.CV.Mat imageF { get; private set; }    //최종수집된 이미지
        public Emgu.CV.Mat imageR { get; private set; }    //최종수집된 이미지

        public void SetImage(Emgu.CV.Mat imgF_, Emgu.CV.Mat imgR_)
        {
            if (this.imageF != null)
            {
                this.imageF.Dispose();
                this.imageF = null;
            }

            //이미지를 신규로 해석하고 데이터를 복사한다  210121
            this.imageF = new Emgu.CV.Mat(imgF_.Size, Emgu.CV.CvEnum.DepthType.Cv8U, 1);
            imgF_.CopyTo(this.imageF);

            if (this.imageR != null)
            {
                this.imageR.Dispose();
                this.imageR = null;
            }

            //이미지를 신규로 해석하고 데이터를 복사한다  210121
            this.imageR = new Emgu.CV.Mat(imgF_.Size, Emgu.CV.CvEnum.DepthType.Cv8U, 1);
            imgR_.CopyTo(this.imageR);

        }

        public void SetImage(Emgu.CV.Mat img_)
        {
            if (this.imageF != null)
            {
                this.imageF.Dispose();
                this.imageF = null;
            }


            if (this.imageR != null)
            {
                this.imageR.Dispose();
                this.imageR = null;
            }

            //이미지를 신규로 해석하고 데이터를 복사한다  210121
            this.imageF = new Emgu.CV.Mat(img_.Size, Emgu.CV.CvEnum.DepthType.Cv8U, 1);
            img_.CopyTo(this.imageF);

        }


        public System.Drawing.Color GetColorByBarcodeCount(int idx)
        {
            if (QRPositionData[idx] > 0) return Color.Gold; //QR데이터가있다면 금색으로 한다

            var Cnt = LabelPositionData[idx];
            if (Cnt == MaxBarcodePosData) return Color.Purple;
            else if (Cnt == 0) return Color.FromArgb(32, 32, 32);
            {
                //나머진 숫자별로 데이터를 표시한다 (
                var GValue = Cnt * 10;
                if (GValue > 255) GValue = 255;
                return Color.FromArgb(32, 32, GValue);
            }

        }
        public Boolean isMaxBarcodePosition(int idx)
        {
            return LabelPositionData[idx] == MaxBarcodePosData;
        }

        public byte[] QRPositionData { get; private set; }
        public byte[] LabelPositionData { get; private set; }

        /// <summary>
        /// keyence barcodeparse 같은데에서 분석한 자료를 이곳에 추가합니다.
        /// 이 데이터는 SPS에서 처리완료됩니다.
        /// </summary>
        public ConcurrentDictionary<String, Class.KeyenceBarcodeData> barcodelist;

        /// <summary>
        /// keyence 로 부터 신규 바코드가 업데이트되었다
        /// </summary>
        public Boolean BarcodeTouched = false;

        public event PropertyChangedEventHandler PropertyChanged;

        //리더기로부터 읽은 자료 모두가 들어잇다
        //public List<Class.KeyenceBarcodeData> barcodelist
        //{
        //    get { return _barcodelist; }
        //    set
        //    {
        //        this._barcodelist = value;
        //        UpdateBarcodePositionData();
        //    }
        //}



        public byte MaxBarcodePosData { get; private set; }
        /// <summary>
        /// 바코드목록을 이용해서 라벨위치 분포값을 변경합낟.
        /// 해당 위치값은 labelposdata로 접근가능함
        /// </summary>
        public void UpdateBarcodePositionData()
        {
            LabelPositionData[0] = (byte)barcodelist.Where(t => t.Value.LabelPosition == 1).Count();
            LabelPositionData[1] = (byte)barcodelist.Where(t => t.Value.LabelPosition == 2).Count();
            LabelPositionData[2] = (byte)barcodelist.Where(t => t.Value.LabelPosition == 3).Count();

            LabelPositionData[3] = (byte)barcodelist.Where(t => t.Value.LabelPosition == 4).Count();
            LabelPositionData[4] = (byte)barcodelist.Where(t => t.Value.LabelPosition == 6).Count();

            LabelPositionData[5] = (byte)barcodelist.Where(t => t.Value.LabelPosition == 7).Count();
            LabelPositionData[6] = (byte)barcodelist.Where(t => t.Value.LabelPosition == 8).Count();
            LabelPositionData[7] = (byte)barcodelist.Where(t => t.Value.LabelPosition == 9).Count();

            QRPositionData[0] = (byte)barcodelist.Where(t => t.Value.LabelPosition == 1 && t.Value.AmkorData.isValid).Count();
            QRPositionData[1] = (byte)barcodelist.Where(t => t.Value.LabelPosition == 2 && t.Value.AmkorData.isValid).Count();
            QRPositionData[2] = (byte)barcodelist.Where(t => t.Value.LabelPosition == 3 && t.Value.AmkorData.isValid).Count();

            QRPositionData[3] = (byte)barcodelist.Where(t => t.Value.LabelPosition == 4 && t.Value.AmkorData.isValid).Count();
            QRPositionData[4] = (byte)barcodelist.Where(t => t.Value.LabelPosition == 6 && t.Value.AmkorData.isValid).Count();

            QRPositionData[5] = (byte)barcodelist.Where(t => t.Value.LabelPosition == 7 && t.Value.AmkorData.isValid).Count();
            QRPositionData[6] = (byte)barcodelist.Where(t => t.Value.LabelPosition == 8 && t.Value.AmkorData.isValid).Count();
            QRPositionData[7] = (byte)barcodelist.Where(t => t.Value.LabelPosition == 9 && t.Value.AmkorData.isValid).Count();

            MaxBarcodePosData = LabelPositionData.Max(t => t);
        }

        /// <summary>
        /// Data1(인쇄전 인식데이터) 과 Data2(QR)가 동일한지 비교합니다.
        /// </summary>
        public Boolean MatchValidation
        {
            get
            {
                if (PARTNO == null) this.PARTNO = string.Empty;
                if (PARTNO2 == null) this.PARTNO2 = string.Empty;
                if (QTY == null) QTY = string.Empty;
                if (QTY2 == null) QTY2 = string.Empty;
                if (SID == null) SID = string.Empty;
                if (SID2 == null) SID2 = string.Empty;
                if (VLOT == null) VLOT = string.Empty;
                if (VLOT2 == null) VLOT2 = string.Empty;
                if (PARTNO == null) PARTNO = string.Empty;
                if (PARTNO2 == null) PARTNO2 = string.Empty;

                if (QTY.Equals(QTY2) == false)
                {
                    PUB.log.AddE(string.Format("QR Validation Failed Quantity:{0} != {1}", QTY, QTY2));
                    return false;
                }
                if (RID.Equals(RID2) == false)
                {
                    PUB.log.AddE(string.Format("QR Validation Failed RID:{0} != {1}", RID, RID2));
                    return false;
                }
                if (VLOT.Equals(VLOT2) == false)
                {
                    PUB.log.AddE(string.Format("QR Validation Failed VLOT:{0} != {1}", VLOT, VLOT2));
                    return false;
                }
                if (PARTNO.Equals(PARTNO2) == false)
                {
                    PUB.log.AddE(string.Format("QR Validation Failed PARTNO:{0} != {1}", PARTNO, PARTNO2));
                    return false;
                }
                if (SID.Equals(SID2) == false)
                {
                    PUB.log.AddE(string.Format("QR Validation Failed SID:{0} != {1}", SID, SID2));
                    return false;
                }

                return true;
            }
        }

        public string QRInputRaw { get; set; }  //입력에 사용한 RAW
        public string QROutRaw { get; set; }    //부착된 QR코드의 값
        public string ZPL { get; set; } //출력시 사용한 ZPL
        public string PrintQRData { get; set; }  //출력시 사용한 ZPL에 포함된 QR데이터
        public string LastQueryStringSID = string.Empty;
        public string LastQueryStringWMS = string.Empty;
        public string LastQueryStringCNV = string.Empty;
        public string LastQueryStringJOB = string.Empty;

        public VisionData(string reason)
        {
            Clear(reason, false);
        }
        public Boolean isEmpty()
        {
            return RID.isEmpty();
        }
        public void Clear(string reason, Boolean timeBackup)
        {
            LastQueryStringSID = string.Empty;
            LastQueryStringWMS = string.Empty;
            LastQueryStringCNV = string.Empty;
            LastQueryStringJOB = string.Empty;
            RetryLoader = 0;
            ApplyOffset = false;
            var baktime = new DateTime(1982, 11, 23);
            if (timeBackup) baktime = this.STime;
            bcdMessage = new List<string>();

            PositionAngle = 0;
            HASHEADER = false;
            CUSTCODE = string.Empty;
            CUSTNAME = string.Empty;
            RID0 = string.Empty;
            RIDNew = false;
            LightOn = false;
            //SCODE = string.Empty;
            ValidSkipbyUser = false;
            NeedCylinderForward = false;
            ApplyAngle = 0;
            MaxBarcodePosData = 0;
            PrintPositionCheck = false;
            LabelPositionData = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 };
            QRPositionData = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 };
            ReelSize = eCartSize.None;
            // PrintForce = false;
            ConfirmAuto = false;
            ConfirmUser = false;
            ConfirmBypass = false;
            if (imageF != null)
            {
                imageF.Dispose();
                imageF = null;
            }
            if (imageR != null)
            {
                imageR.Dispose();
                imageR = null;
            }
            ServerUpdate = false;
            PrintPositionData = "";
            //LabelPos = "";
            if (barcodelist != null) barcodelist.Clear();
            else barcodelist = new ConcurrentDictionary<string, KeyenceBarcodeData>();

            QRInputRaw = string.Empty;
            QROutRaw = string.Empty;
            ZPL = string.Empty;
            PrintQRData = string.Empty;

            STime = baktime;// DateTime.Parse("1982-11-23");
            ETime = DateTime.Parse("1982-11-23");
            GTime = DateTime.Parse("1982-11-23");
            Complete = false;
            //Angle = 0.0;
            //AngleQR = false;
            //AngleSTD = false;
            MCN = string.Empty;
            Target = string.Empty;
            Ready = false;
            QTY0 = string.Empty;
            QTY = string.Empty;// string.Empty;
            QTYRQ = false;
            //PUB.log.AddI($"비젼개체 CLEAR 로 RQ 상태 초기화(false)");

            BATCH = string.Empty;
            QTYMAX = string.Empty;

            SID0 = string.Empty;
            SID = string.Empty;
            //RID = string.Empty;
            SetRID(string.Empty, reason);
            VLOT = string.Empty;
            MFGDATE = string.Empty;
            VNAME = string.Empty;
            PARTNO = string.Empty;

            QTY2 = "0";// string.Empty;
            SID2 = string.Empty;
            RID2 = string.Empty;
            VLOT2 = string.Empty;
            MFGDATE2 = string.Empty;
            VNAME2 = string.Empty;
            PARTNO2 = string.Empty;

            FileNameL = string.Empty;
            FileNameU = string.Empty;

            MFGDATE_Trust = false;
            PARTNO_Trust = false;
            QTY_Trust = false;
            SID_Trust = false;
            RID_Trust = false;
            VLOT_Trust = false;
            VNAME_Trust = false;

            BarcodeTouched = false;
            MCN = string.Empty;
            Target = string.Empty;

            PUB.log.Add($"Vision Data Deleted ({reason})");
        }

        public void CopyTo(ref VisionData obj)
        {
            //바코드메세지 복사
            obj.bcdMessage = new List<string>();
            foreach (var item in this.bcdMessage)
                obj.bcdMessage.Add(item);

            obj.ApplyOffset = this.ApplyOffset;
            obj.ConfirmAuto = this.ConfirmAuto;
            obj.ConfirmUser = this.ConfirmUser;
            obj.CUSTCODE = this.CUSTCODE;
            obj.CUSTNAME = this.CUSTNAME;
            obj.LightOn = this.LightOn;

            //obj.SCODE = this.SCODE;
            obj.ValidSkipbyUser = this.ValidSkipbyUser;
            obj.NeedCylinderForward = this.NeedCylinderForward; //210207
            obj.ApplyAngle = this.ApplyAngle; //210207
            obj.STime = this.STime;
            obj.ETime = this.ETime;
            obj.GTime = this.GTime;
            obj.FileNameL = this.FileNameL;
            obj.FileNameU = this.FileNameU;
            obj.Complete = this.Complete;
            //obj.Angle = this.Angle;
            //obj.AngleQR = this.AngleQR;
            //obj.AngleSTD = this.AngleSTD;
            obj.BATCH = this.BATCH;
            obj.QTYMAX = this.QTYMAX;
            obj.Ready = this.Ready;
            obj.QTY = this.QTY;
            obj.QTYRQ = this.QTYRQ;
            obj.SID = this.SID;
            obj.SID0 = this.SID0; //210331
            obj.SetRID(this.RID, "copy");//	 obj.RID = this.RID;
            obj.RID0 = this.RID0;
            obj.RIDNew = this.RIDNew;
            obj.VLOT = this.VLOT;
            obj.VNAME = this.VNAME;
            obj.MFGDATE = this.MFGDATE;
            obj.PARTNO = this.PARTNO;
            obj.MCN = this.MCN;
            obj.Target = this.Target;

            obj.QTY2 = this.QTY2;
            obj.SID2 = this.SID2;
            obj.RID2 = this.RID2;
            obj.VLOT2 = this.VLOT2;
            obj.VNAME2 = this.VNAME2;
            obj.MFGDATE2 = this.MFGDATE;
            obj.PARTNO2 = this.PARTNO2;

            obj.QRInputRaw = this.QRInputRaw;
            obj.QROutRaw = this.QROutRaw;
            obj.ZPL = this.ZPL;
            obj.PrintQRData = this.PrintQRData;
            obj.PrintPositionData = this.PrintPositionData;
            //obj.PrintForce = this.PrintForce;
            obj.ReelSize = this.ReelSize;
            obj.PrintPositionCheck = this.PrintPositionCheck;
            obj.BarcodeTouched = this.BarcodeTouched;

            //라벨위치값 복사
            for (int i = 0; i < obj.LabelPositionData.Length; i++)
                obj.LabelPositionData[i] = this.LabelPositionData[i];
            for (int i = 0; i < obj.QRPositionData.Length; i++)
                obj.QRPositionData[i] = this.QRPositionData[i];
            if (obj.imageF != null)
            {
                obj.imageF.Dispose();
                obj.imageF = null;
            }
            if (obj.imageR != null)
            {
                obj.imageR.Dispose();
                obj.imageR = null;
            }
            //이미지를 복사해준다. 210121
            if (this.imageF != null)
            {
                obj.imageF = new Emgu.CV.Mat(this.imageF.Size, Emgu.CV.CvEnum.DepthType.Cv8U, 1);
                this.imageF.CopyTo(obj.imageF);
            }
            if (this.imageR != null)
            {
                obj.imageR = new Emgu.CV.Mat(this.imageR.Size, Emgu.CV.CvEnum.DepthType.Cv8U, 1);
                this.imageR.CopyTo(obj.imageR);
            }

            //바코드 데이터를 복사해준다.             
            if (obj.barcodelist == null)
                obj.barcodelist = new ConcurrentDictionary<string, KeyenceBarcodeData>();// List<KeyenceBarcodeData>();
            else
                obj.barcodelist.Clear();

            foreach (var item in this.barcodelist)
            {
                var bcd = item.Value;
                var newitema = new KeyenceBarcodeData
                {
                    Angle = bcd.Angle,
                    CenterPX = new Point(bcd.CenterPX.X, bcd.CenterPX.Y),
                    Data = bcd.Data,
                    LabelPosition = bcd.LabelPosition,
                    UserActive = bcd.UserActive,
                    barcodeSymbol = bcd.barcodeSymbol,
                };

                newitema.vertex = new Point[bcd.vertex.Length];
                bcd.vertex.CopyTo(newitema.vertex, 0);

                if (bcd.AmkorData != null) //231006 null error fix
                    bcd.AmkorData.CopyTo(newitema.AmkorData);

                obj.barcodelist.AddOrUpdate(item.Key, newitema,
                    (key, data) =>
                    {
                        data.Angle = newitema.Angle;
                        data.CenterPX = newitema.CenterPX;
                        data.Data = newitema.Data;
                        data.LabelPosition = newitema.LabelPosition;
                        data.UserActive = newitema.UserActive;
                        data.barcodeSymbol = newitema.barcodeSymbol;
                        data.RegExConfirm = newitema.RegExConfirm;
                        return data;
                    });
            }


        }

        public void UpdateTo(ref VisionData obj)
        {
            //바코드메세지 복사
            obj.bcdMessage = new List<string>();
            foreach (var item in this.bcdMessage)
                obj.bcdMessage.Add(item);

            obj.ApplyOffset = this.ApplyOffset;
            obj.ConfirmAuto = this.ConfirmAuto;
            obj.ConfirmUser = this.ConfirmUser;
            obj.CUSTCODE = this.CUSTCODE;
            obj.CUSTNAME = this.CUSTNAME;
            obj.LightOn = this.LightOn;

            //obj.SCODE = this.SCODE;
            obj.ValidSkipbyUser = this.ValidSkipbyUser;
            obj.NeedCylinderForward = this.NeedCylinderForward; //210207
            obj.ApplyAngle = this.ApplyAngle; //210207
            obj.STime = this.STime;
            obj.ETime = this.ETime;
            obj.GTime = this.GTime;
            obj.FileNameL = this.FileNameL;
            obj.FileNameU = this.FileNameU;
            obj.Complete = this.Complete;
            //obj.Angle = this.Angle;
            //obj.AngleQR = this.AngleQR;
            //obj.AngleSTD = this.AngleSTD;
            obj.Ready = this.Ready;
            obj.QTY = this.QTY;
            obj.QTYRQ = this.QTYRQ;
            obj.SID = this.SID;
            obj.SID0 = this.SID0; //210331
            obj.SetRID(this.RID, "copy");//	 obj.RID = this.RID;
            obj.RID0 = this.RID0;
            obj.RIDNew = this.RIDNew;
            obj.VLOT = this.VLOT;
            obj.VNAME = this.VNAME;
            obj.MFGDATE = this.MFGDATE;
            obj.PARTNO = this.PARTNO;
            obj.MCN = this.MCN;
            obj.Target = this.Target;

            obj.BATCH = this.BATCH;
            obj.QTYMAX = this.QTYMAX;
            obj.QTY2 = this.QTY2;
            obj.SID2 = this.SID2;
            obj.RID2 = this.RID2;
            obj.VLOT2 = this.VLOT2;
            obj.VNAME2 = this.VNAME2;
            obj.MFGDATE2 = this.MFGDATE;
            obj.PARTNO2 = this.PARTNO2;

            obj.QRInputRaw = this.QRInputRaw;
            obj.QROutRaw = this.QROutRaw;
            obj.ZPL = this.ZPL;
            obj.PrintQRData = this.PrintQRData;
            obj.PrintPositionData = this.PrintPositionData;
            //obj.PrintForce = this.PrintForce;
            obj.ReelSize = this.ReelSize;
            obj.PrintPositionCheck = this.PrintPositionCheck;
            obj.BarcodeTouched = this.BarcodeTouched;

            //라벨위치값 복사
            for (int i = 0; i < obj.LabelPositionData.Length; i++)
                obj.LabelPositionData[i] = this.LabelPositionData[i];
            for (int i = 0; i < obj.QRPositionData.Length; i++)
                obj.QRPositionData[i] = this.QRPositionData[i];
            if (obj.imageF != null)
            {
                obj.imageF.Dispose();
                obj.imageF = null;
            }
            if (obj.imageR != null)
            {
                obj.imageR.Dispose();
                obj.imageR = null;
            }
            //이미지를 복사해준다. 210121
            if (this.imageF != null)
            {
                obj.imageF = new Emgu.CV.Mat(this.imageF.Size, Emgu.CV.CvEnum.DepthType.Cv8U, 1);
                this.imageF.CopyTo(obj.imageF);
            }
            if (this.imageR != null)
            {
                obj.imageR = new Emgu.CV.Mat(this.imageR.Size, Emgu.CV.CvEnum.DepthType.Cv8U, 1);
                this.imageR.CopyTo(obj.imageR);
            }
            //바코드 데이터를 복사해준다.             
            if (obj.barcodelist == null)
                obj.barcodelist = new ConcurrentDictionary<string, KeyenceBarcodeData>();// List<KeyenceBarcodeData>();
            else
                obj.barcodelist.Clear();

            foreach (var item in this.barcodelist)
            {
                var bcd = item.Value;
                var newitema = new KeyenceBarcodeData
                {
                    Angle = bcd.Angle,
                    CenterPX = new Point(bcd.CenterPX.X, bcd.CenterPX.Y),
                    Data = bcd.Data,
                    LabelPosition = bcd.LabelPosition,
                    UserActive = bcd.UserActive,
                    barcodeSymbol = bcd.barcodeSymbol,
                };

                newitema.vertex = new Point[bcd.vertex.Length];
                bcd.vertex.CopyTo(newitema.vertex, 0);
                bcd.AmkorData.CopyTo(newitema.AmkorData);
                obj.barcodelist.AddOrUpdate(item.Key, newitema,
                    (key, data) =>
                    {
                        data.Angle = newitema.Angle;
                        data.CenterPX = newitema.CenterPX;
                        data.Data = newitema.Data;
                        data.LabelPosition = newitema.LabelPosition;
                        data.UserActive = newitema.UserActive;
                        data.barcodeSymbol = newitema.barcodeSymbol;
                        data.RegExConfirm = newitema.RegExConfirm;
                        return data;
                    });
            }


        }
    }
}
