using o0.Geometry;
using Org.BouncyCastle.Utilities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UI;

namespace o0.Project
{
    public partial class InfraredIdentification
    {
        public Geometry2D.Vector<int> Size;
        public InfraredIdentification(Geometry2D.Vector<int> Size)
        {
            this.Size = Size;
        }

        int DelayWhite = 0;
        int CaptureWhite = 0;
        int DelayBlack = 0;
        int CaptureBlack = 0;
        Geometry.Vector<float>[] ScreenLocateTexture = null;
        int ScreenCaptureCount = 0;
        public void LocateScreen(int Capture = 30, int Delay = 30)//frame
        {
            DelayWhite = Delay;
            CaptureWhite = Capture;
            DelayBlack = Delay;
            CaptureBlack = Capture;
            ScreenCaptureCount = Capture;
            o0WebCamera.SetScreen(UnityEngine.Color.white);
        }
        public void Update(WebCamTexture texture)
        {
            if (texture.width != Size.x || texture.height != Size.y)
                return;//纹理大小不一致

            if (DelayWhite != 0)
            {
                DelayWhite--;
                return;
            }
            if (CaptureWhite != 0)
            {
                CaptureWhite--;
                if(ScreenLocateTexture == null)
                    ScreenLocateTexture = new Geometry.Vector<float>[Size.x * Size.y];
                var pixel = texture.GetPixels();
                Parallel.For(0, Size.x * Size.y, i =>
                {
                    var ip = pixel[i];
                    ScreenLocateTexture[i] += new Geometry.Vector<float>(ip.r, ip.g, ip.b);
                });
                if (CaptureWhite == 0)
                    o0WebCamera.SetScreen(UnityEngine.Color.black);
                return;
            }
            if (DelayBlack != 0)
            {
                DelayBlack--;
                return;
            }
            if (CaptureBlack != 0)
            {
                CaptureBlack--;
                var pixel = texture.GetPixels();
                Parallel.For(0, Size.x * Size.y, i =>
                {
                    var ip = pixel[i];
                    ScreenLocateTexture[i] -= new Geometry.Vector<float>(ip.r, ip.g, ip.b);
                });
                if (CaptureBlack == 0)
                {
                    o0WebCamera.SetScreen(null);
                    UnityEngine.Color[] newPixel = new UnityEngine.Color[Size.x * Size.y];

                    Parallel.For(0, Size.x * Size.y, i => {
                        var pi = ScreenLocateTexture[i] /= ScreenCaptureCount;
                        newPixel[i] = new UnityEngine.Color(pi.x, pi.y, pi.z);
                    });

                    //读取数据
                    {
                        var fileName = "屏幕定位数据20230505_145229.bin";
                        ScreenLocateTexture = $"TestData/{fileName}".FileReadByte<Vector<float>[]>();
                        Debug.Log($"Read {fileName}");
                        Parallel.For(0, Size.x * Size.y, i =>
                        {
                            var pi = ScreenLocateTexture[i];
                            newPixel[i] = new UnityEngine.Color(pi.x, pi.y, pi.z);
                        });
                    }

                    var ScreenLocateTex = new Texture2D(Size.x, Size.y);
                    ScreenLocateTex.SetPixels(newPixel);
                    ScreenLocateTex.Apply();
                    //o0WebCamera.DebugTexture(2, ScreenLocateTex);
                    var ScreenLocateTexLighted = ScreenLocateTex.AutoLight(10);
                    o0WebCamera.DebugTexture(2, ScreenLocateTexLighted);
                    //var FileSavePath = Application.persistentDataPath + "/ScreenLocateTexture.bin";
                    bool Save = false;
                    if (Save)
                    {
                        var FileSavePath = "屏幕定位数据.bin";
                        FileSavePath.FileWriteByte(ScreenLocateTexture);
                        Debug.Log("ScreenLocateTexture Saved To: " + FileSavePath);
                    }

                    var ScreenLocateTexR = ScreenLocateTexLighted.ToRGB(ColorChannel.Red);
                    var ScreenLocateTexG = ScreenLocateTexLighted.ToRGB(ColorChannel.Green);
                    var ScreenLocateTexB = ScreenLocateTexLighted.ToRGB(ColorChannel.Blue);
                    o0WebCamera.DebugTexture(3, ScreenLocateTexR);
                    //o0WebCamera.DebugTexture(4, ScreenLocateTexG);
                    //o0WebCamera.DebugTexture(5, ScreenLocateTexB);


                    var watch = new System.Diagnostics.Stopwatch();
                    watch.Start();
                    var times = new List<double>() { 0.0 };



                    var ScreenLocateTexLightedMat = ScreenLocateTexLighted.Too0Mat();
                    //var ScreenLocateTexLightedMat = texture.Too0Mat();

                    //var (edge, edgeDir) = ScreenLocateTexLightedMat.IdentifyEdge();
                    var (edge, edgeDir) = ScreenLocateTexLightedMat.zimIdentifyEdgeGradientAny(15);
                    //o0WebCamera.DebugTexture(4, ScreenLocateTexLighted.Too0Mat().IdentifyEdgeGradient().ToTex());
                    o0WebCamera.DebugTexture(4, edge.ToTex());

                    var quadLines = ScreenLocateTexLightedMat.ZIMIdentifyQuadLSD(edge, edgeDir, out List<Geometry2D.Float.Line> lightLines, 15, 100);

                    var drawLineMap = new Matrix(edge.Size, Tiling: true);
                    //drawLineMap.DrawLine(quadLines[0], (x, y) => 1, new Geometry2D.Float.Vector(0, 10));
                    foreach (var l in quadLines)
                    {
                        if (l != null)
                            drawLineMap.DrawLine(l, (x, y) => 1, new Geometry2D.Float.Vector(0, 10));
                    }


                    //var lines = edge.IdentifyLineLSD(edgeDir, 100);
                    ////var lines = ScreenLocateTexLightedMat.IdentifyLineLSD();

                    //var drawLineMap = new MatrixF2D(edge.Size.x, edge.Size.y);
                    //var returnMaxLines = lines.Sub(0, 10);
                    //foreach (var (line, sum, gradient) in returnMaxLines)
                    //    drawLineMap.DrawLine(line, (x, y) => 1, new Geometry2D.Float.Vector(0, 10));

                    o0WebCamera.DebugTexture(5, drawLineMap.ToTex());

                    drawLineMap = new Matrix(edge.Size, Tiling: true);
                    for (int i = 0; i < lightLines.Count; i++)
                    {
                        var l = lightLines[i];
                        if (i < 4)
                            drawLineMap.DrawLine(l, (x, y) => 1, new Geometry2D.Float.Vector(0, 10));

                        else
                            drawLineMap.DrawLine(l, (x, y) => 1, new Geometry2D.Float.Vector(0, 2));
                    }
                    o0WebCamera.DebugTexture(2, drawLineMap.ToTex());

                    times.Add(watch.ElapsedMilliseconds);
                    UnityEngine.Debug.Log("time: " + (times[times.Count - 1] - times[times.Count - 2]));

                    //o0WebCamera.DebugTexture(5, edge.IdentifyLine(edgeDir).ToTex());
                    //o0WebCamera.DebugTexture(4, ScreenLocateTexLighted.Too0Mat().IdentifyEdgeGradientX().ToTex());
                    //o0WebCamera.DebugTexture(5, ScreenLocateTexLighted.Too0Mat().IdentifyEdgeGradientY().ToTex());

                    //var convolutionLighted2 = ScreenLocateTexLighted.Too0Mat().IdentifyEdgeVariance().ToTex();

                    // opecncv处理
                    // zim
                    {
                        //var cvLines = edge.cvHoughLinesP();
                        //o0WebCamera.DebugTexture(5, cvLines);

                        //var myLines = Hough.Transform(edgeMat);
                        //var cvLines = edge.cvLine(myLines);
                        //o0WebCamera.DebugTexture(5, cvLines);
                    }


                    //o0WebCamera.DebugTexture(4, convolutionLighted2);
                }

                return;
            }

            /*
            var avg = new Geometry4D.Vector<float>();
            var pixel = texture.GetPixels();
            foreach(var i in pixel.Index())
            {
                var iP = pixel[i];
                avg += new Geometry4D.Vector<float>(iP.r, iP.g, iP.b, iP.a);
            }
            avg /= pixel.Count();/**/

            var newTex = texture.AutoLight(10);

            o0WebCamera.DebugTexture(1, newTex);/**/

            var texLightedR = newTex.ToRGB(ColorChannel.Red);
            var texLightedG = newTex.ToRGB(ColorChannel.Green);
            var texLightedB = newTex.ToRGB(ColorChannel.Blue);
            o0WebCamera.DebugTexture(3, texLightedR);
            o0WebCamera.DebugTexture(4, texLightedG);
            o0WebCamera.DebugTexture(5, texLightedB);/**/
            //Debug.Log(avg);
        }


    }
}
