using System;
using System.Collections.Generic;
using EmreIstikam001.component.TehranOffice.ToosForAll;
using EmreIstikam001.Properties;
using Grasshopper.Kernel;
using Rhino;
using Rhino.Geometry;
using Rhino.Input.Custom;
using Rhino.Input;
using Bitmap = System.Drawing.Bitmap;
using Color = System.Drawing.Color;
using Rhino.Display;

namespace EmreIstikam001.component.TehranOffice.Components.ÇİZİM_YARDIMCILARI.DetailSymbol
{
    public class DetailSymbolGH : BaseGhComponent
    {
        protected override string CodeName => "DETAIL_SYMBOL";
        protected override GH_Exposure? ValidExposure => GH_Exposure.quarternary;
        private string AxId = "A5-1";
        private readonly string BlockName = "DETAIL_SYMBOL_0";
        private readonly DetailSymbolFRM frm = new DetailSymbolFRM();
        private Point3d Pt = Point3d.Unset;
        private List<Point3d> InputPoints = new List<Point3d>();
        private Polyline aaa;
        new List<Point3d> PointsToDrawLeader = new List<Point3d>();
        private double Scale = 1.00;
        private bool DisposePriview = false;
        private bool btnClicked = false;
        private static Int32 PatternId = 64512;
        public DetailSymbolGH()
            : base("DETAIL SYMBOL", "DS",
                "DETAIL SYMBOL",
                "PARDUS", "ÇİZİM YARDIMCILARI")
        {
            frm.cmb1.TextChanged += GetScale;
            frm.txt1.TextChanged += GetAxId;
            frm.btn1.Click += ButtonClickedGetPoint;
            frm.FormClosed += CloseForm;
            frm.btnDispose.Click += CloseForm;
        }
        protected override Bitmap Icon => Resources.AksBalonuCi̇zme;
        public override Guid ComponentGuid => new Guid("3f706da9-1d53-4b13-b421-93083f5de516");
        private void ButtonClickedGetPoint(object sender, EventArgs e)
        {
            btnClicked = true;
            CustomConduit conduit = null;
            DisposePriview = false;
            aaa = Get2PointWithSnap("Insert 1 Noktası", "Insert 2 Noktası");

            ExpireSolution(true);
            //frm.Close();

            if (conduit != null)
            {
                conduit.Enabled = false;  // Disable the old conduit
                RhinoDoc.ActiveDoc.Views.Redraw();  // Redraw the view
            }

            // Prepare to show the new geometry
            
        }
        private void GetScale(object sender, EventArgs e)
        {
            Scale = Convert.ToDouble(frm.cmb1.Text);
        }
        private void GetAxId(object sender, EventArgs e)
        {
            AxId = frm.txt1.Text;
        }
        private void CloseForm(object sender, EventArgs e)
        {

            DisposePriview = true;
            ExpireSolution(true);
        }
        protected override void RegisterInputParams(GH_InputParamManager pManager)
        {
        }
        protected override void RegisterOutputParams(GH_OutputParamManager pManager)
        {
        }
        protected override void AuthenticatedSolveInstance(IGH_DataAccess DA)
        {
            frm.Show();
            List<Curve> rectanglesegments = new List<Curve>();
            List<Curve> Filletrectanglesegments = new List<Curve>();
            List<TextEntity> textent = new List<TextEntity>();
            List<Leader> leaders = new List<Leader>();

            if (aaa != null && btnClicked)
            {
                rectanglesegments.AddRange(aaa.ToNurbsCurve().DuplicateSegments());
                CustomShowGeometry(rectanglesegments, textent, leaders, Filletrectanglesegments, DisposePriview, 3, 61680);

                PointsToDrawLeader = EIGetRihnoTl.Get2Point("Insert Noktasi 1", "Insert Noktasi 2");
            }

            var doc = RhinoDoc.ActiveDoc;

            if (PointsToDrawLeader.Count > 1)
            {
                /****text create  ****/
                string styleName;
                if (Scale > 9)
                    styleName = $"PCY 2.5mm 1/{Scale}";
                else
                    styleName = $"PCY 2.5mm 1/0{Scale}";
                var leaderStyle = doc.DimStyles.FindName(styleName);
                var pt3 = PointsToDrawLeader[1];
                pt3.Transform(Transform.Translation(Vector3d.XAxis * 3 * Scale));
                // for detect rhite toleft point selected or revers
                if (PointsToDrawLeader[0].X > PointsToDrawLeader[1].X)
                    pt3.Transform(Transform.Translation(-Vector3d.XAxis * 6 * Scale));
                PointsToDrawLeader.Add(pt3);
                var leader = Leader.CreateWithRichText("", Plane.WorldXY, leaderStyle, PointsToDrawLeader.ToArray());

                Pt = leader.Points3D[2];
                var xAxis = doc.Views.ActiveView.ActiveViewport.ConstructionPlane().XAxis;
                var yAxis = doc.Views.ActiveView.ActiveViewport.ConstructionPlane().YAxis;
                if (Pt != Point3d.Unset)
                {
                    var txtObj = new TextEntity();
                    txtObj.Text = AxId;
                    var txtPlane = new Plane(Pt, xAxis, yAxis);
                    txtObj.Plane = txtPlane;
                    //string styleName;
                    if (Scale > 9)
                        styleName = $"PCY 5mm 1/{Scale}";
                    else
                        styleName = $"PCY 5mm 1/0{Scale}";
                    var textStyle = doc.DimStyles.FindName(styleName);
                    txtObj.ParentDimensionStyle = textStyle;
                    txtObj.TextHeight = 5;
                    txtObj.Justification = TextJustification.MiddleCenter;
                    var txt2Bbox = txtObj.GetBoundingBox(true);
                    var xDim = txt2Bbox.Max.X - txt2Bbox.Min.X;
                    var yDim = txt2Bbox.Max.Y - txt2Bbox.Min.Y;
                    if (PointsToDrawLeader[0].X > PointsToDrawLeader[1].X)
                        txtObj.Plane = new Plane(Pt + new Vector3d(-Math.Max(xDim / 2 + 6, 6) * Scale, 0, 0), xAxis, yAxis);
                    else
                    {
                        txtObj.Plane = new Plane(Pt + new Vector3d(Math.Max(xDim / 2 + 6, 6) * Scale, 0, 0), xAxis, yAxis);
                    }
                    var rec = new Rectangle3d(txtObj.Plane, Math.Max(xDim + 12, 12) * Scale, Math.Max(yDim + 2, 4) * Scale);
                    var trnsfrm = new Transform(Transform.Translation(new Vector3d(-Math.Max(xDim / 2 + 6, 6) * Scale * xAxis - Math.Max(yDim / 2 + 1, 2) * Scale * yAxis)));
                    rec.Transform(trnsfrm);
                    var rec2 = Curve.CreateFilletCornersCurve(rec.ToNurbsCurve(), Math.Min(rec.Width, rec.Height) / 2,
                        0.01,
                        0.01);
                    //doc.Objects.Add(txtObj);
                    //doc.Objects.Add(rec2);
                    Filletrectanglesegments.Add(rec2);
                    textent.Add(txtObj);
                }
                leaders.Add(leader);
                
            }

           
            if (PointsToDrawLeader.Count>1)
            {
                CustomShowGeometry(rectanglesegments, textent,leaders,Filletrectanglesegments, DisposePriview, 3, 61680);
            }
            btnClicked = false;
        }



        public static Polyline Get2PointWithSnap(string command, string command2)
        {
            var doc = RhinoDoc.ActiveDoc;
            var points = new List<Point3d>();
            Point3d pt0;

            // Step 1: Get the first corner of the rectangle
            using (var getPointAction = new GetPoint())
            {
                getPointAction.SetCommandPrompt("Select the first corner of the rectangle:");
                if (getPointAction.Get() != GetResult.Point)
                {
                    RhinoApp.WriteLine("No point was selected.");
                    return null;
                }
                pt0 = getPointAction.Point();
            }

            Point3d pt1;

            // Step 2: Get the opposite corner with dynamic drawing
            using (var getPointAction = new GetPoint())
            {
                getPointAction.SetCommandPrompt("Select the opposite corner of the rectangle:");
                getPointAction.SetBasePoint(pt0, true);
                getPointAction.DynamicDraw += (sender, e) =>
                {
                    Point3d currentPt = e.CurrentPoint;

                    // Define other three corners based on pt0 and currentPt
                    Point3d pt2 = new Point3d(currentPt.X, pt0.Y, pt0.Z);
                    Point3d pt3 = new Point3d(pt0.X, currentPt.Y, pt0.Z);

                    // Draw temporary rectangle
                    e.Display.DrawPatternedLine(pt0, pt2, Color.CornflowerBlue, 61680, 2);
                    e.Display.DrawPatternedLine(pt2, currentPt, Color.CornflowerBlue, 61680, 2);
                    e.Display.DrawPatternedLine(currentPt, pt3, Color.CornflowerBlue, 61680, 2);
                    e.Display.DrawPatternedLine(pt3, pt0, Color.CornflowerBlue, 61680, 2);
                };

                if (getPointAction.Get() != GetResult.Point)
                {
                    RhinoApp.WriteLine("No end point was selected.");
                    return null;
                }
                pt1 = getPointAction.Point();
            }
            // Step 3: Create the rectangle polyline
            var rectangle = new Polyline(new[] { pt0, new Point3d(pt1.X, pt0.Y, pt0.Z), pt1, new Point3d(pt0.X, pt1.Y, pt1.Z), pt0 });
            return rectangle;
        }

        public static CustomConduit conduit = null;

        public static void CustomShowGeometry(
            List<Curve> curves,
            List<TextEntity> texts,
            List<Leader> leaders,
            List<Curve> rec2Curves,
            bool disposeDisplay,
            int thickness,
            int pattern)
        {
            // If disposeDisplay is true, disable and remove the current conduit
            if (disposeDisplay && conduit != null)
            {
                conduit.Enabled = false;  // Disable the conduit
                RhinoDoc.ActiveDoc.Views.Redraw();  // Force a redraw to remove the preview
                conduit = null;  // Clear the conduit instance
                return;  // Exit as we've removed the conduit
            }

            // If no conduit exists, create and enable a new one
            if (!disposeDisplay && conduit == null)
            {
                conduit = new CustomConduit(
                    curves,
                    texts,
                    leaders,
                    rec2Curves,
                    Color.Green,        // Set desired colors
                    Color.Green,
                    Color.Green,
                    Color.Green,
                    thickness,
                    pattern);
                conduit.Enabled = true;  // Enable the conduit
                RhinoDoc.ActiveDoc.Views.Redraw();  // Force Rhino to redraw the view
            }
            else if (conduit != null)
            {
                // Update the existing conduit with new curves
                conduit.UpdateAll(curves, texts, leaders, rec2Curves);
                RhinoDoc.ActiveDoc.Views.Redraw();  // Force a redraw to update the display
            }
        }



        // Conduit class that handles the display of geometry
        public class CustomConduit : DisplayConduit
        {
            private List<Curve> _curves;
            private List<TextEntity> _texts;
            private List<Leader> _leaders;
            private List<Curve> _rec2Curves; // Assuming rec2 is a filleted rectangle represented as curves
            private Color _curveColor;
            private Color _rec2Color;
            private Color _textColor;
            private Color _leaderColor;
            private int _thickness;
            private int _pattern;

            public CustomConduit(
                List<Curve> curves,
                List<TextEntity> texts,
                List<Leader> leaders,
                List<Curve> rec2Curves,
                Color curveColor,
                Color textColor,
                Color leaderColor,
                Color rec2Color,
                int thickness,
                int pattern)
            {
                _curves = curves ?? new List<Curve>();
                _texts = texts ?? new List<TextEntity>();
                _leaders = leaders ?? new List<Leader>();
                _rec2Curves = rec2Curves ?? new List<Curve>();
                _curveColor = curveColor;
                _textColor = textColor;
                _leaderColor = leaderColor;
                _rec2Color = rec2Color;
                _thickness = thickness;
                _pattern = pattern;
            }

            
            //comprehensive update method
            public void UpdateAll(
                List<Curve> curves,
                List<TextEntity> texts,
                List<Leader> leaders,
                List<Curve> rec2Curves)
            {
                _curves = curves ?? new List<Curve>();
                _texts = texts ?? new List<TextEntity>();
                _leaders = leaders ?? new List<Leader>();
                _rec2Curves = rec2Curves ?? new List<Curve>();
            }

            // Override DrawOverlay to render all geometry types
            protected override void DrawOverlay(DrawEventArgs e)
            {
                // Draw Curves
                foreach (var curve in _curves)
                {
                    if (curve != null && curve.IsValid)
                    {

                        Line line = new Line(curve.PointAtStart, curve.PointAtEnd);
                        e.Display.DrawPatternedLine(line, _curveColor, _pattern, _thickness);

                    }
                }

                // Draw rec2 Curves (filleted rectangle)
                foreach (var curve in _rec2Curves)
                {
                    if (curve != null && curve.IsValid)
                    {
                        e.Display.DrawCurve(curve, _rec2Color, _thickness);
                    }
                }

                // Draw Leaders
                foreach (var leader in _leaders)
                {
                    if (leader != null && leader.IsValid)
                    {
                        Line leaderShow = new Line(leader.Points3D[0], leader.Points3D[2]);
                        e.Display.DrawLine(leaderShow, _leaderColor, 3);
                    }
                }

                // Draw TextEntities
                foreach (var text in _texts)
                {
                    if (text != null && text.IsValid)
                    {
                        // Draw the text. Use DrawText for simple text or DrawTextDot for more complex cases
                        // Here, we'll use DrawTextDot for better visualization
                        e.Display.DrawText(text, _textColor);
                    }
                }
            }
        }
    }
}