using AR;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Project
{
    public partial class FMain
    {

        private void Keyence_BarcodeRecv(object sender, Device.KeyenceBarcode.RecvDataEvent e)
        {
            var dev = sender as Device.KeyenceBarcode;
            if (e.RawData.StartsWith("ERROR"))
            {
                //로그가 너무 많이 쌓이니 해제한다
                //Pub.log.AddE("Reader RES : " + resp);
            }
            else if (e.RawData.StartsWith("OK,BLOAD"))
            {
                var str = e.RawData.Replace("\r", "").Replace("\n", "");
                PUB.log.AddI($"[{dev.Tag}] {str}");
            }
            else if (e.RawData.StartsWith("OK,BSAVE"))
            {
                var str = e.RawData.Replace("\r", "").Replace("\n", "");
                PUB.log.AddI($"[{dev.Tag}] {str}");
            }
            else if (e.RawData.StartsWith("OK"))
            {
                //OK회신
            }
            else
            {
                //값은 받았다
                if (PUB.sm.Step != eSMStep.HOME_FULL && PUB.sm.Step != eSMStep.HOME_QUICK)
                {
                    //							PUB.logKeyence.Add($"{resp.Replace("\n", "").Replace("\r", "")}");
                    var rawdata = e.RawData; //↔▲▼
                    rawdata = rawdata.Replace('\x1D', '↔').Replace('\x1E', '▲').Replace('\x04', '▼');

                    var lines = rawdata.Split(new char[] { '\r' },StringSplitOptions.RemoveEmptyEntries);
                    foreach(var line in lines)
                        ParseBarcode(line, dev.Tag.ToString());
                }
                else
                {
                    //PUB.logKeyence.Add($"Code Ignore by Home Process({resp.Replace("\n", "").Replace("\r", "")})");
                }
            }
        }

        bool imageprocess = false;
        private void Keyence_ImageRecv(object sender, Device.KeyenceBarcode.RecvImageEvent e)
        {

            var dev = sender as Device.KeyenceBarcode;
            System.Windows.Forms.PictureBox keyenceview;
            if (dev.Tag == "R") keyenceview = keyenceviewR;
            else keyenceview = keyenceviewF;

            if (imageprocess == false)
            {
                imageprocess = true;

                if (PUB.sm.Step >= eSMStep.IDLE && this.IsDisposed == false && this.Disposing == false)
                {

                    //var oimage = this.pictureBox1.Image;
                    //this.pictureBox1.Image = e.Image;
                    //if (oimage != null) oimage.Dispose();

                    if (keyenceview.Image == null)
                    {
                        //var newbitmap = new Bitmap(e.Image.Width,e.Image.Height, e.Image.PixelFormat);
                        var old = keyenceview.Image;
                        //var newbitmap = PUB.keyence.CreateBitmap(e.Image.Width, e.Image.Height);
                        //PUB.keyence.UpdateBitmap((Bitmap)e.Image, newbitmap);
                        keyenceview.Image = e.Image;
                        if (old != null) old.Dispose();
                        PUB.log.AddAT("First image received");
                    }
                    else
                    {
                        //내용ㅁㄴ업데이트하자
                        var preimage = keyenceview.Image as Bitmap;
                        keyenceview.Image = e.Image;
                        if (preimage != null) preimage.Dispose();
                        //PUB.keyence.UpdateBitmap((Bitmap)e.Image, preimage);
                        //this.pictureBox2.Invalidate();
                    }


                }

                if (this.IsDisposed)
                {
                    dev.Dispose();
                }

                imageprocess = false;
            }
        }

        double GetAngle(Point pt1, Point pt2)
        {
            var val = Math.Asin((pt2.Y - pt1.Y) / Math.Sqrt(Math.Pow(pt2.X - pt1.X, 2.0) + Math.Pow(pt2.Y - pt1.Y, 2.0)));


            double retval = 0.0;
            if ((pt2.X - pt1.X) >= 0 && (pt2.Y - pt1.Y) >= 0)
                retval = val;
            else if ((pt2.X - pt1.X) < 0 && (pt2.Y - pt1.Y) >= 0)
                retval = Math.PI - val;
            else if ((pt2.X - pt1.X) < 0 && (pt2.Y - pt1.Y) < 0)
                retval = Math.PI - val;
            else if ((pt2.X - pt1.X) >= 0 && (pt2.Y - pt1.Y) < 0)
                retval = Math.PI * 2 + val;

            return retval;
        }

        private string KeyenceBarcodeDataF = string.Empty;
        private string KeyenceBarcodeDataR = string.Empty;


        /// <summary>
        /// 키엔스로부터 받은 데이터를 분석한다.
        /// </summary>
        /// <param name="response"></param>
        /// <param name="Source"></param>
        void ParseBarcode(string response, string Source)
        {

            

            //220901 - 특문있었ㅇ츰
            var r1 = (char)0x1D;
            var r2 = (char)0x1E;
            var r3 = (char)0x04;
            var r4 = (char)0x00;
            response = response.Replace(r1.ToString(), "");
            response = response.Replace(r2.ToString(), "");
            response = response.Replace(r3.ToString(), "");
            response = response.Replace(r4.ToString(), "");
            response = response.Replace("\r", "");
            response = response.Replace("\n", "");
            response = response.Replace("\0", "");
            response = response.RemoveNoneASCII().Trim();

            ///101409576:522/1171:427/1143:429/1134:524/1155:475/1151\r
            var frames = response.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
            var itemC = PUB.Result.ItemDataC;

            //키엔스바코드패턴검사
            var Pattern = @"^(\d+):(\w+.*):(\d+/\d+):(\d+/\d+):(\d+/\d+):(\d+/\d+):(\d+/\d+)";
            Pattern = @"^(\d+):(.*):(\d+/\d+):(\d+/\d+):(\d+/\d+):(\d+/\d+):(\d+/\d+)";
            var RegX = new System.Text.RegularExpressions.Regex(Pattern);
            foreach (var resp in frames)
            {
                var bcddata = resp.Trim().Split(',');
                if (resp.Equals("0:ERROR"))
                {
                    PUB.log.AddE($"[{Source}] {resp}");
                    continue;
                }
                else if (bcddata.Length > 2 && bcddata[1] == "BLOAD")
                {
                    if (bcddata[0] == "ER")
                    {
                        PUB.log.AddE($"[{Source}]Bacode Memory Read Error({resp})");
                    }
                    else
                    {
                        PUB.log.AddI($"[{Source}]Bacode Memory Read Complete({resp})");
                    }
                    continue;
                }
                else if (bcddata.Length > 2 && bcddata[1] == "BSAVE")
                {
                    if (bcddata[0] == "ER")
                    {
                        PUB.log.AddE($"[{Source}]Bacode Memory Read Error({resp})");
                    }
                    else
                    {
                        PUB.log.AddI($"[{Source}]Bacode Memory Read Complete({resp})");
                    }
                    continue;
                }
                else if (RegX.IsMatch(resp.Trim()) == false)
                {
                    //에러처리 221018
                    if (resp.StartsWith("0:ERROR")) continue;

                    PUB.log.AddE($"***Barcode({Source}) response data error value (please check Keyence transmission format) " + resp);
                    listView21.SetText(9, 3, "ERR");//.setTitle(8, 1, "ERR");
                    continue;
                }

                if (AR.VAR.BOOL[eVarBool.JOB_PickON_Retry])  //221110
                {
                    if (PUB.sm.Step == eSMStep.RUN)
                        PUB.log.AddAT($"Picker({Source}) is retrying, ignoring barcode:{resp}");
                    continue;
                }

                var MatchList = RegX.Matches(resp.Trim());
                var buf = MatchList[0].Groups;

                var angle = 0;
                var sym = buf[1].Value; //symbol
                var vData = buf[2].Value.Trim();    //data

                if (Source == "R") KeyenceBarcodeDataR = vData; //rear
                else KeyenceBarcodeDataF = vData;   //front

                //바코드 무시조건 확인
                //if (PUB.Result.BCDIgnorePattern != null)
                //{
                //	Boolean ignore = false;
                //	foreach (var ignoreitem in PUB.Result.BCDIgnorePattern)
                //	{
                //		if (ignoreitem.Pattern.isEmpty()) continue;
                //		RegX = new System.Text.RegularExpressions.Regex(ignoreitem.Pattern);
                //		if (RegX.IsMatch(vData))
                //		{
                //			var igmsg = "무시바코드 Patter: " + ignoreitem.Pattern + ",값=" + vData;
                //			ignore = true;
                //			break;
                //		}
                //	}
                //	if (ignore) continue;
                //}

                var vV1 = buf[3].Value.Split('/');
                var vV2 = buf[4].Value.Split('/');
                var vV3 = buf[5].Value.Split('/');
                var vV4 = buf[6].Value.Split('/');
                var vCP = buf[7].Value.Split('/');

                var vertex = new Point[4];
                vertex[0] = new Point(int.Parse(vV1[0]), int.Parse(vV1[1]));
                vertex[1] = new Point(int.Parse(vV2[0]), int.Parse(vV2[1]));
                vertex[2] = new Point(int.Parse(vV3[0]), int.Parse(vV3[1]));
                vertex[3] = new Point(int.Parse(vV4[0]), int.Parse(vV4[1]));
                var vertextCP = new Point(int.Parse(vCP[0]), int.Parse(vCP[1]));

                var ReelCP = Point.Empty;
                if (itemC.VisionData.ReelSize == eCartSize.Inch13)
                    ReelCP = AR.SETTING.Data.CenterPosition13;
                else
                    ReelCP = AR.SETTING.Data.CenterPosition7;

                //각도를 이곳에서 처리함
                angle = (int)(GetAngle(vertex[0], vertex[1]) * 180.0 / Math.PI);

                //var atkstdbcd = new StdLabelPrint.CAmkorSTDBarcode(vData);
                //if (atkstdbcd.DisposalCode) //사용하지않는 103코드라면 아에 처리안함
                //{
                //	PUB.log.AddE("***폐기된 103 코드형태라 처리하지 않음" + vData);
                //	continue;
                //}

                //특정좌표가 기준점으로부터 몇도 틀어져 있는가? 
                //math.atan2(PY - CY, PX - CX)

                //회전후좌표계산
                //x = root((px - cx) ^ 2 + (py - cy) ^ 2) * cos@ +cx
                //y = root(px ^ 2 + py ^ 2) * sin@   +cy
                double theta = 0.0;// Pub.Result.ItemData[1].VisionData.BaseAngle;
                if (itemC.VisionData.BaseAngle(out string msg, out Class.KeyenceBarcodeData angbcd))
                {
                    theta = angbcd.Angle;
                }

                var theta_rad = -theta * Math.PI / 180.0;
                var PX = (int)(Math.Cos(theta_rad) * (vertextCP.X - ReelCP.X) - Math.Sin(theta_rad) * (vertextCP.Y - ReelCP.Y)) + ReelCP.X;
                var PY = (int)(Math.Sin(theta_rad) * (vertextCP.X - ReelCP.X) + Math.Cos(theta_rad) * (vertextCP.Y - ReelCP.Y)) + ReelCP.Y;

                float LabelAngRad = (float)(Math.Atan2(PY - ReelCP.Y, PX - ReelCP.X));// 2;  //라벨의 위치값을 찾아서 입력해야한다.
                var labelpos = (float)(LabelAngRad * 180.0 / Math.PI);
                if (labelpos < 0) labelpos = 360 + labelpos;

                byte lp = 0;

                if (labelpos >= 15 * 22.5 && labelpos <= 360) lp = 6;
                else if (labelpos >= 0 && labelpos <= 22.5) lp = 6;
                else if (labelpos >= 1 * 22.5 && labelpos <= 3 * 22.5) lp = 3;
                else if (labelpos >= 3 * 22.5 && labelpos <= 5 * 22.5) lp = 2;
                else if (labelpos >= 5 * 22.5 && labelpos <= 7 * 22.5) lp = 1;
                else if (labelpos >= 7 * 22.5 && labelpos <= 9 * 22.5) lp = 4;
                else if (labelpos >= 9 * 22.5 && labelpos <= 11 * 22.5) lp = 7;
                else if (labelpos >= 11 * 22.5 && labelpos <= 13 * 22.5) lp = 8;
                else if (labelpos >= 13 * 22.5 && labelpos <= 15 * 22.5) lp = 9;
                else
                {

                }

                //중첩된 데이터가 있는가?
                lock (itemC.VisionData.barcodelist)
                {
                    //키값에 소스위치도 같이 포함한다
                    var valuekey = Source + vData;
                    var bcdin = itemC.VisionData.barcodelist.ContainsKey(valuekey);//.Where(t => t.Value.CheckIntersect(vertextCP, vData) == true).FirstOrDefault();
                    if (bcdin == false)
                    {
                        //신규바코드데이터이므로 추가한다.
                        PUB.logKeyence.Add($"{resp.Replace("\n", "").Replace("\r", "")}");
                        var newitem = new Class.KeyenceBarcodeData()
                        {
                            AmkorData = new StdLabelPrint.CAmkorSTDBarcode(vData),
                            CenterPX = vertextCP,
                            Data = vData,
                            vertex = vertex,
                            Angle = angle,
                            LabelPosition = lp,
                            barcodeSymbol = sym,
                            barcodeSource = Source,
                        };

                        var addok = itemC.VisionData.barcodelist.TryAdd(valuekey, newitem);
                        if (addok) PUB.log.Add($"[O]BCD RESERV[NEW:{sym}] " + Source + " " + vData);
                        else PUB.log.AddE($"[X]BCD RESERV[NEW:{sym}] " + Source + " " + vData);

                        itemC.VisionData.UpdateBarcodePositionData();
                        itemC.VisionData.BarcodeTouched = true;
                    }
                    else
                    {
                        //기존데이터와 좌표가 겹치면 두고 다르면 업데이트한다
                        var predata = itemC.VisionData.barcodelist[valuekey];
                        if (predata.CheckIntersect(vertextCP, vData) == false)
                        {
                            var newitem = new Class.KeyenceBarcodeData()
                            {
                                AmkorData = new StdLabelPrint.CAmkorSTDBarcode(vData),
                                CenterPX = vertextCP,
                                Data = vData,
                                vertex = vertex,
                                Angle = angle,
                                LabelPosition = lp,
                                barcodeSymbol = sym,
                                barcodeSource = Source,
                            };

                            //기존정보를 지우고
                            PUB.log.Add($"[UPD]BCD RESERV:{sym}] " + Source + " " + vData);
                            itemC.VisionData.barcodelist[valuekey] = newitem;
                            itemC.VisionData.UpdateBarcodePositionData();
                            itemC.VisionData.BarcodeTouched = true;
                        }
                    }
                }

                listView21.SetText(9, 3, $"{angle} > {theta}");
                listView21.SetText(10, 3, itemC.VisionData.QRInputRaw.isEmpty() ? $"DETECT" : $"NONE");
                listView21.SetText(13, 2, $"LABEL");
                listView21.SetText(13, 3, $"{labelpos:N1}");
            }
        }

        Boolean IsSIDValue(string data)
        {
            if (data.Length != 9) return false;
            decimal a = 0;
            if (decimal.TryParse(data, out a) == false) return false;
            if (data.StartsWith("10") == false) return false;
            return true;
        }
        Boolean IsDateValue(string date, out string datestr)
        {
            //821123 과 19821123 의 데이터를 판별한다
            datestr = string.Empty;
            date = date.Replace("-", "").Replace("/", "");
            if (date.Length == 6)
            {
                var vy = date.Substring(0, 2);
                var vm = date.Substring(2, 2);
                var vd = date.Substring(4, 2);
                if (isDigit(vy) == false || isDigit(vm) == false || isDigit(vd) == false)
                    return false;
                if (vy.toInt() < 0 || vy.toInt() > 29) return false;
                if (vm.toInt() < 1 || vm.toInt() > 12) return false;
                if (vd.toInt() < 1 || vd.toInt() > 21) return false;
                datestr = "20" + vy + vm + vd;
                return true;

            }
            else if (date.Length == 8)
            {
                var vy = date.Substring(0, 4);
                var vm = date.Substring(4, 2);
                var vd = date.Substring(6, 2);
                if (isDigit(vy) == false || isDigit(vm) == false || isDigit(vd) == false)
                    return false;
                if (vy.toInt() < 2000 || vy.toInt() > 2900) return false;
                if (vm.toInt() < 1 || vm.toInt() > 12) return false;
                if (vd.toInt() < 1 || vd.toInt() > 31) return false;
                datestr = vy + vm + vd;
                return true;
            }
            else return false;
        }
        Boolean isDigit(string v)
        {
            int a;
            return int.TryParse(v, out a);
        }


        string cmd = string.Empty;
        DateTime LastTrigOnTime = DateTime.Now;
        Boolean bTrgOn = false;
        //private void Keyence_Trigger(bool bOn)
        //{

        //	if (PUB.flag.get(eVarBool.KEYENCE_TRIGGER) == bOn) return;

        //	if (bOn)
        //		cmd = "LON";
        //	else
        //		cmd = "LOFF";

        //	if (bOn) LastTrigOnTime = DateTime.Now;

        //	string resp = reader.ExecCommand(cmd);
        //	bTrgOn = bOn;
        //	PUB.logKeyence.Add("BARCODE", $"트리거 전송({cmd})");
        //	_isCrevisACQ[1] = bOn;

        //	//트리거
        //	PUB.flag.set(eVarBool.KEYENCE_TRIGGER, bOn, "JOB");
        //}
        private void SaveImage(string filename)
        {
            var fi = new System.IO.FileInfo(filename);
            var ext = fi.Extension;
            var nameonly = fi.FullName.Replace(fi.Extension, "");
            var fiF = new System.IO.FileInfo(nameonly + "F" + ext);
            var fiR = new System.IO.FileInfo(nameonly + "F" + ext);


            if (PUB.keyenceF != null)
            {
                var img = this.keyenceviewF.Image;
                if (img == null) return;
                using (var newimg = new Bitmap(img.Width, img.Height, img.PixelFormat))
                {
                    PUB.keyenceR.UpdateBitmap((Bitmap)img, newimg);
                    if (fiF.Directory.Exists == false) fiF.Directory.Create();
                    if (fiF.Exists) fiF.Delete();
                    newimg.Save(fiF.FullName);
                }
            }

            if (PUB.keyenceR != null)
            {
                var img = this.keyenceviewR.Image;
                if (img == null) return;
                using (var newimg = new Bitmap(img.Width, img.Height, img.PixelFormat))
                {
                    PUB.keyenceR.UpdateBitmap((Bitmap)img, newimg);
                    if (fiR.Directory.Exists == false) fiR.Directory.Create();
                    if (fiR.Exists) fiR.Delete();
                    newimg.Save(fiR.FullName);
                }
            }
        }
    }
}
