using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using Rhino;
using Rhino.DocObjects;
using Rhino.Geometry;
using Grasshopper.Kernel;
using EmreIstikam001.component.TehranOffice.FormGH._3D_DEN_2D_YE;
using EmreIstikam001.component.TehranOffice.ToosForAll;
using EmreIstikam001.Properties;
using EmreIstikam001.component.TehranOffice.ZAbsolute.Tools;
using Eto.Forms;
using Eto.Drawing;
using Rhino.Display;
using Bitmap = System.Drawing.Bitmap;

namespace EmreIstikam001.component.TehranOffice.Components._3D_DEN_2D_YE
{
    /// <summary>
    /// Creates a detail from a 3D block.
    /// </summary>
    public class PaftalamDetayAlma22GH : BaseGhComponent
    {
        private PaftalamaDetayAlmaFrm frm = new PaftalamaDetayAlmaFrm();
        private List<Curve> Rectangle = new List<Curve>();
        private readonly List<Curve> PreviewCurvesList = new List<Curve>();
        private bool ShowGeometry = true;
        private bool bake = false;
        private bool IsCloseForm = false;
        private string BlockName;
        private Guid GUID;
        private Make2dResult HiddenAndVisibleCurves;
        private List<GeometryBase> CuttedBlockGeo = new List<GeometryBase>();

        private List<Curve> RectangleSegments0 = new List<Curve>();
        private List<Point3d> MiddlePointsRectangle = new List<Point3d>();

        public PaftalamDetayAlma22GH()
            : base("DETAY ALMA6969696969", "P",
                "DETAY ALMA",
                "PARDUS", "3D'DEN 2D'YE")
        {
            frm.btnBlock.Click += AddBlock;
            frm.btnRec.Click += SelectRectangle;
            frm.txtName.TextChanged +=       ControlValueChanged;
            frm.cmbScaleText.TextChanged +=  ControlValueChanged;
            frm.cmbScaleDraw.TextChanged +=  ControlValueChanged;
            frm.cmbLayer.TextChanged +=      ControlValueChanged;
            frm.chbHidden.CheckedChanged +=  ControlValueChanged;
            frm.radTurkey.CheckedChanged +=  ControlValueChanged;
            frm.radEnglish.CheckedChanged += ControlValueChanged;
            frm.radRussian.CheckedChanged += ControlValueChanged;
            frm.btnBake.Click += Bake;
            frm.Closed += Frm_Closed;
        }
        protected override string CodeName => "DETAY_ALMA";
        protected override GH_Exposure? ValidExposure => GH_Exposure.primary;
        protected override Bitmap Icon => Resources.DETAY_ALMA;

        private void ControlValueChanged(object sender, EventArgs e)
        {
            ExpireSolution(true);
        }
        private void SelectRectangle(object sender, EventArgs e)
        {
            Rectangle.Clear();
            Rectangle = EIGetRihnoTl.GetPolylineCurve("Select region. ", false, false, false, false, out GUID);
            if (Rectangle[0] != null) RectangleSegments0.AddRange(Rectangle[0].DuplicateSegments());
            ExpireSolution(true);
        }
        private void Frm_Closed(object sender, EventArgs e)
        {
            if (IsCloseForm) bake = true;
            ShowGeometry = false;
            ExpireSolution(true);
        }
        private void Bake(object sender, EventArgs e)
        {
            IsCloseForm = true;
            frm.Close();
        }
        public void AddBlock(object sender, EventArgs e)
        {
            BlockName = EIGetRihnoTl.GetNameBlock("Block Seç", false, true)[0];
            ExpireSolution(true);
        }
        

        protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
        {
        }
        protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
        {
        }

        protected override void AuthenticatedSolveInstance(IGH_DataAccess DA)
        {
            frm.Show();
            PreviewCurvesList.Clear();
            List<GeometryBase> rectangleGeometries = new List<GeometryBase>();
            List<GeometryBase> make2dGeometries = new List<GeometryBase>();
            List<GeometryBase> geometries = new List<GeometryBase>();
            var doc = RhinoDoc.ActiveDoc;
            var currentDocPlane = doc.Views.ActiveView.ActiveViewport.ConstructionPlane();
            if (Rectangle.Count > 0)
            {
                // Section 1: Get Block Geometries
                List<GeometryBase> blockGeo = GetBlockGeometries(doc, BlockName, out var boundingBoxGeo, out var objectHeights);

                // Section 2: Get and Fillet Rectangle
                var filletRectangle = GetFilletedRectangle(currentDocPlane, Rectangle[0]);
                //Section 2
                var rectangleOrg = Rectangle[0];
                Curve[] rectangleSegments = rectangleOrg.DuplicateSegments();
                List<Point3d> rectanglePts = new List<Point3d>();
                for (int i = 0; i < rectangleSegments.ToList().Count; i++) { rectanglePts.Add(rectangleSegments[i].PointAtEnd); }
                List<double> distances = new List<double>();
                for (int i = 0; i < rectanglePts.Count; i++) { distances.Add(rectanglePts[0].DistanceTo(rectanglePts[i])); }
                var furthestPt = rectanglePts[distances.IndexOf(distances.Max())];
                var rectangleBase = new Rectangle3d(currentDocPlane, furthestPt, rectanglePts[0]);
                //var filletRectangle = Curve.CreateFilletCornersCurve(rectangleBase.ToNurbsCurve(), rectangleBase.Circumference / 30, doc.ModelAbsoluteTolerance, doc.ModelAngleToleranceRadians);
                var filletRectangleBoundingBox = EIGeometryTl.boundigboxCurve(new List<Curve> { filletRectangle });
                var rectangleMovement = boundingBoxGeo.Min.Z - filletRectangleBoundingBox.Center.Z;
                Transform rectangleTrans = Transform.Translation(currentDocPlane.ZAxis * rectangleMovement);
                filletRectangle.Transform(rectangleTrans);
                rectangleBase.Transform(rectangleTrans);
                rectangleGeometries.Add(filletRectangle);
                PreviewCurvesList.Add(filletRectangle);
                //Section 3
                var rectangleBoundingBox = EIGeometryTl.boundigboxCurve(new List<Curve> { filletRectangle });
                var text = new TextEntity();
                string detay = "DETAY-";
                if (frm.radTurkey.Checked)
                {
                    detay = "DETAY-";
                }
                if (frm.radEnglish.Checked)
                {
                    detay = "DETAIL-";
                }

                if (frm.radRussian.Checked)
                {
                    detay = "ДЕТАЛИ-";
                }
                text.Text = detay + frm.txtName.Text;
                var textScale = Convert.ToDouble(frm.cmbScaleText.Text);
                var textStyleText = doc.DimStyles.FindName($"PCY 2.5mm 1/01");
                if (textScale < 9) textStyleText = doc.DimStyles.FindName($"PCY 2.5mm 1/0{textScale}");
                else textStyleText = doc.DimStyles.FindName($"PCY 2.5mm 1/{textScale}");
                text.ParentDimensionStyle = textStyleText;
                text.Justification = TextJustification.MiddleCenter;
                var minY0 = rectangleBoundingBox.Y.T0;
                var textLocationPoint = new Point3d(rectangleBoundingBox.Center.X, minY0 - (5 * (Convert.ToDouble(frm.cmbScaleText.Text))), rectangleBoundingBox.Center.Z);
                var plane = new Plane(textLocationPoint, currentDocPlane.XAxis, currentDocPlane.YAxis);
                text.Plane = plane;
                rectangleGeometries.Add(text);
                PreviewCurvesList.AddRange(text.Explode());
                //Section 4
                Curve rectangleBase2 = rectangleBase.ToNurbsCurve().DuplicateCurve();
                //rectangleBase2.Transform(moveRec);
                var rectangleExtrusion1 = Surface.CreateExtrusion(rectangleBase2.ToNurbsCurve(), Vector3d.ZAxis * objectHeights * 2);
                Brep rectangleExtrusionCapped1 = rectangleExtrusion1.ToBrep().CapPlanarHoles(doc.ModelAbsoluteTolerance);
                List<Brep> blockGeoBreps = new List<Brep>();
                for (int i = 0; i < blockGeo.Count; i++) blockGeoBreps.Add(Brep.TryConvertBrep(blockGeo[i]));
                List<Brep> extrusion1List = new List<Brep> { rectangleExtrusionCapped1 };
                Brep[] cuttingresult1 = Brep.CreateBooleanDifference(blockGeoBreps, extrusion1List, doc.ModelAbsoluteTolerance, false);
                CuttedBlockGeo = new List<GeometryBase>();
                CuttedBlockGeo.AddRange(cuttingresult1);
                for (int i = 0; i < RectangleSegments0.Count; i++)
                {
                    MiddlePointsRectangle.Add(RectangleSegments0[i].PointAt(RectangleSegments0[i].GetLength() / 2));
                }
                HiddenAndVisibleCurves = Make2d(CuttedBlockGeo);
                List<Curve> checkForVerticalCurvesVisible = new List<Curve>();
                var visibleProjectedCurves = new List<Curve>(HiddenAndVisibleCurves.curveVis);
                var hiddenProjectedCurves = new List<Curve>(HiddenAndVisibleCurves.curveHid);
                double tolerance = 0.0001;
                for (int i = visibleProjectedCurves.Count - 1; i >= 0; i--)
                {
                    Point3d curveMiddle = new Point3d();
                    curveMiddle = visibleProjectedCurves[i].PointAt(visibleProjectedCurves[i].GetLength() / 2);
                    bool isOnCurve0 =
                       Math.Abs(Math.Round(curveMiddle.Y) - Math.Round(MiddlePointsRectangle[0].Y)) < tolerance;
                    bool isOnCurve1 =
                       Math.Abs(Math.Round(curveMiddle.X) - Math.Round(MiddlePointsRectangle[1].X)) < tolerance;
                    bool isOnCurve2 =
                       Math.Abs(Math.Round(curveMiddle.Y) - Math.Round(MiddlePointsRectangle[2].Y)) < tolerance;
                    bool isOnCurve3 =
                       Math.Abs(Math.Round(curveMiddle.X) - Math.Round(MiddlePointsRectangle[3].X)) < tolerance;

                    if (isOnCurve0 || isOnCurve2)
                    {
                        checkForVerticalCurvesVisible.Add(HiddenAndVisibleCurves.curveVis[i]);
                        visibleProjectedCurves.RemoveAt(i);
                    }
                    if (isOnCurve1 || isOnCurve3)
                    {
                        checkForVerticalCurvesVisible.Add(HiddenAndVisibleCurves.curveVis[i]);
                        visibleProjectedCurves.RemoveAt(i);
                    }
                }
                RemoveSmallCurvesUnderLarger(checkForVerticalCurvesVisible);
                RemoveDuplicateCurves(checkForVerticalCurvesVisible);

                Curve[] joinedCurves = Curve.JoinCurves(checkForVerticalCurvesVisible, RhinoDoc.ActiveDoc.ModelAbsoluteTolerance);

                //Section 5
                var bbox = BoundingBox.Empty;
                foreach (var obj in visibleProjectedCurves)
                {
                    var objBbox = obj.GetBoundingBox(true);
                    bbox.Union(objBbox);
                }
                var box = new Box(bbox);
                var boundingBoxBlock = box;

                Transform scaleGeo = Transform.Scale(boundingBoxBlock.GetCorners()[0], Convert.ToDouble(frm.cmbScaleDraw.Text));
                for (int i = 0; i < visibleProjectedCurves.Count; i++) visibleProjectedCurves[i].Transform(scaleGeo);
                for (int i = 0; i < hiddenProjectedCurves.Count; i++) hiddenProjectedCurves[i].Transform(scaleGeo);
                for (int i = 0; i < joinedCurves.Length; i++) joinedCurves[i].Transform(scaleGeo);
                //Section 6
                var boundingBoxGeoCut = Make2DUtils.boundigboxGeometry(CuttedBlockGeo);
                var boundingBoxCurvesX = boundingBoxGeoCut.X.T1 - boundingBoxGeoCut.X.T0;
                var XampN = boundingBoxGeo.Max.X - boundingBoxGeoCut.Center.X;
                var XFilletRectangle = filletRectangleBoundingBox.X.T1;
                var movement = 0.0;
                if (XFilletRectangle < boundingBoxGeoCut.X.T1) movement = 50 + (XampN) + (boundingBoxCurvesX / 2);
                else movement = 50 + (XampN) + (boundingBoxCurvesX / 2) + (XFilletRectangle - boundingBoxGeoCut.X.T1);
                var vecMove = Vector3d.XAxis * movement;
                Transform movementSection = Transform.Translation(vecMove);
                for (int a = 0; a < visibleProjectedCurves.ToList().Count; a++) visibleProjectedCurves[a].Transform(movementSection);
                for (int a = 0; a < hiddenProjectedCurves.ToList().Count; a++) hiddenProjectedCurves[a].Transform(movementSection);
                for (int a = 0; a < joinedCurves.ToList().Count; a++) joinedCurves[a].Transform(movementSection);
                //Section 7
                var boundingBoxMovedBlock = Make2DUtils.boundigboxGeometry(CuttedBlockGeo);
                var zmovement = boundingBoxGeo.Min.Z - boundingBoxMovedBlock.Z.T0;
                Transform zTrans = Transform.Translation(Vector3d.ZAxis * zmovement);
                for (int i = 0; i < visibleProjectedCurves.Count; i++) visibleProjectedCurves[i].Transform(zTrans);
                for (int i = 0; i < hiddenProjectedCurves.Count; i++) hiddenProjectedCurves[i].Transform(zTrans);
                geometries.AddRange(visibleProjectedCurves);
                geometries.AddRange(hiddenProjectedCurves);

                //Section 8
                List<Curve> make2dCurves = new List<Curve>();
                List<Curve> projectedVisibleCurves = new List<Curve>();
                List<Curve> projectedHiddenCurves = new List<Curve>();

                for (int i = 0; i < hiddenProjectedCurves.Count; i++)
                {
                    Curve crv;
                    crv = hiddenProjectedCurves[i].DuplicateCurve();
                    crv = Curve.ProjectToPlane(crv, Plane.WorldXY);
                    projectedHiddenCurves.Add(crv);
                }
                //tempHid.AddRange(projectedHiddenCurves);
                for (int i = 0; i < visibleProjectedCurves.Count; i++)
                {
                    Curve crv;
                    crv = visibleProjectedCurves[i].DuplicateCurve();
                    crv = Curve.ProjectToPlane(crv, Plane.WorldXY);
                    projectedVisibleCurves.Add(crv);
                }

                if (frm.chbHidden.Checked)
                {
                    make2dCurves.AddRange(projectedHiddenCurves);
                    make2dCurves.AddRange(projectedVisibleCurves);
                }
                else
                {
                    make2dCurves.AddRange(projectedVisibleCurves);
                }
                make2dGeometries.AddRange(make2dCurves);
                make2dGeometries.AddRange(joinedCurves);
                PreviewCurvesList.AddRange(make2dCurves);
                PreviewCurvesList.AddRange(joinedCurves);
                make2dCurves.AddRange(joinedCurves);
                //Section 9
                var make2dBoundingBox = Make2DUtils.boundigboxCurve(make2dCurves);
                var minY = make2dBoundingBox.Y.T0;
                
                var make2dTextLocation = new Point3d(make2dBoundingBox.Center.X, minY - (10 * textScale), make2dBoundingBox.Center.Z);
                var scaleText = string.Empty;
                if (textScale < 9) scaleText = $"1/0{textScale}";
                else scaleText = $"1/{textScale}";
                var text2 = new TextEntity();
                var textdetay = "";
                if (frm.radTurkey.Checked)
                {
                    textdetay = "DETAY";
                }
                if (frm.radEnglish.Checked)
                {
                    textdetay = "DETAIL";

                }
                if (frm.radRussian.Checked)
                {
                    textdetay = "ДЕТАЛИ";
                }
                text2.Text = $"{textdetay}-{frm.txtName.Text}";
                text2.ParentDimensionStyle = textStyleText;
                text2.Justification = TextJustification.MiddleCenter;
                var plane2 = new Plane(make2dTextLocation, currentDocPlane.XAxis, currentDocPlane.YAxis);
                text2.Plane = plane2;
                make2dGeometries.Add(text2);
                PreviewCurvesList.AddRange(text2.Explode());
                //Section 10
                var value1 = $"{frm.cmbScaleDraw.Text}";
                var value2 = $"{textScale}";
                var values = new List<string> { value1, value2 };
                string layerHidden = string.Empty;
                if (frm.cmbLayer.SelectedIndex == 0 || (frm.cmbLayer.SelectedIndex == 1)) layerHidden = EIAttributesTl.EILayers.EI.PCY_Aluminium.PROFILE_HIDDEN;
                else if (frm.cmbLayer.SelectedIndex == 2) layerHidden = EIAttributesTl.EILayers.EI.PCY_Steel.HIDDEN;
                else if (frm.cmbLayer.SelectedIndex == 3) layerHidden = EIAttributesTl.EILayers.EI.PCY_COMPOSIITE.COMPOSITE_HIDDEN;
                else if (frm.cmbLayer.SelectedIndex == 4) layerHidden = EIAttributesTl.EILayers.EI.PCY_Galvanize.GALVANIZE_SHEET_HIDDEN;
                else if (frm.cmbLayer.SelectedIndex == 5 || frm.cmbLayer.SelectedIndex == 6) layerHidden = EIAttributesTl.EILayers.EI.PCY_STAINLESS_STEEL.STAINLESS_STEEL_HIDDEN;
                else layerHidden = EIAttributesTl.EILayers.EI.PCY_Plastic.PLASTIC_HIDDEN;
                var attributeHidden = new ObjectAttributes();
                var layer_index_hidden = doc.Layers.FindByFullPath(layerHidden, true);
                attributeHidden.LayerIndex = layer_index_hidden;

                var BlockAttributes1 = new ObjectAttributes();
                BlockAttributes1.LayerIndex = doc.Layers[0].Index;

                var keys = new List<string> { "Çizim Ölçeği", "Yazı Ölçeği" };
                var BlockAttributes2 = new ObjectAttributes();
                for (var i = 0; i < keys.Count; i++) BlockAttributes2.SetUserString(keys[i], values[i]);
                var blockLayer = doc.Layers[doc.Layers.FindByFullPath("0", 0)];
                BlockAttributes2.LayerIndex = blockLayer.Index;

                var layers1 = EIAttributesTl.LayersForAllGeomatry(new List<string> { EIAttributesTl.EILayers.EI.PCY_Axis.ARCHITECTURAL, EIAttributesTl.EILayers.EI.PCY_Text.GENERAL }, new List<int> { 1, 1 });
                var attributesRectangle = EIAttributesTl.CreateListOfAttributes(layers1);

                var layerName = $"PCY::{frm.cmbLayer.Text}";
                List<Layer> layers2 = new List<Layer>();
                if (frm.chbHidden.Checked) layers2 = EIAttributesTl.LayersForAllGeomatry(
                    new List<string> { layerHidden, layerName, EIAttributesTl.EILayers.EI.PCY_Others.HIDDEN, EIAttributesTl.EILayers.EI.PCY_Text.GENERAL },
                    new List<int> { hiddenProjectedCurves.Count, visibleProjectedCurves.Count, joinedCurves.Length, 1 });
                else layers2 = EIAttributesTl.LayersForAllGeomatry(
                    new List<string> { layerName, EIAttributesTl.EILayers.EI.PCY_Others.HIDDEN, EIAttributesTl.EILayers.EI.PCY_Text.GENERAL },
                    new List<int> { visibleProjectedCurves.Count, joinedCurves.Length, 1 });
                var attributesMake2d = EIAttributesTl.CreateListOfAttributes(layers2);
                //Section 11
                if (bake)
                {
                    EIBlocksTl.CreateAndBakeBlock($"{BlockName}_DETAY_0", rectangleGeometries, attributesRectangle, BlockAttributes1);
                    EIBlocksTl.CreateAndBakeBlock($"{BlockName}_DETAY_0", make2dGeometries, attributesMake2d, BlockAttributes2);
                }
                EIShowGeomatryTl.ShowGeomatry(PreviewCurvesList, ShowGeometry);
                doc.Objects.Delete(GUID, true);
            }
        }

        public override Guid ComponentGuid
        {
            get { return new Guid("a1831019-78c3-4da5-9313-3ea30c01abdc"); }
        }

        #region  Methods
        private List<GeometryBase> GetBlockGeometries(RhinoDoc doc, string blockName, out BoundingBox boundingBoxGeo, out double objectHeights)
        {
            var blockGeo = new List<GeometryBase>();
            var allInstances = doc.InstanceDefinitions;
            var findBlock = allInstances.FirstOrDefault(d => d.Name == blockName);
            if (findBlock != null)
            {
                var objBlock = findBlock.GetReferences(0)?.FirstOrDefault();
                if (objBlock != null)
                {
                    blockGeo.AddRange(objBlock.GetSubObjects().Select(subObj => subObj.Geometry));
                }
            }
            boundingBoxGeo = BoundigboxGeometry(blockGeo);
            objectHeights = boundingBoxGeo.Max.Z - boundingBoxGeo.Min.Z;
            return blockGeo;
        }
        public static BoundingBox BoundigboxGeometry(List<GeometryBase> objects)
        {
            var bbox = BoundingBox.Empty;
            foreach (var obj in objects)
            {
                if (obj != null)
                {
                    var objBbox = obj.GetBoundingBox(true);
                    bbox.Union(objBbox);
                }
            }
            return bbox;
        }

        private Curve GetFilletedRectangle(Plane currentDocPlane, Curve rectangleCurve)
        {
            var rectangleSegments = rectangleCurve.DuplicateSegments();
            var rectanglePts = rectangleSegments.Select(s => s.PointAtStart).ToList();
            var furthestPt = rectanglePts.OrderByDescending(pt => rectanglePts[0].DistanceTo(pt)).FirstOrDefault();
            var rectangleBase = new Rectangle3d(currentDocPlane, furthestPt, rectanglePts[0]);
            var filletRadius = rectangleBase.Circumference / 30;
            var filletRectangle = Curve.CreateFilletCornersCurve(rectangleBase.ToNurbsCurve(), filletRadius, RhinoDoc.ActiveDoc.ModelAbsoluteTolerance, RhinoDoc.ActiveDoc.ModelAngleToleranceRadians);
            return filletRectangle;
        }

        #endregion

        /// <summary>
        /// Initializes a make2D of a list of geometries
        /// </summary>
        /// <param name="geometries"> list of geometries </param>
        /// <returns> Visible and hidden curves </returns>
        public static Make2dResult Make2d(List<GeometryBase> geometries)
        {
            List<Curve> projectedVisibleCurves = new List<Curve>();
            List<Curve> projectedHiddeCurves = new List<Curve>();
            var doc = RhinoDoc.ActiveDoc;
            if (doc == null)
            {
                RhinoApp.WriteLine("No active document found.");
                return null;
            }
            RhinoViewport topView = new RhinoViewport();
            foreach (RhinoView view in doc.Views.GetStandardRhinoViews())
            {
                if (view.MainViewport.Name == "Top")
                {
                    topView = view.MainViewport;
                    break;
                }
            }
            var hld_params = new HiddenLineDrawingParameters
            {
                AbsoluteTolerance = 0.01,
                IncludeTangentEdges = false,
                IncludeHiddenCurves = true
            };
            hld_params.SetViewport(topView);
            List<BoundingBox> allGeoB = new List<BoundingBox>();
            var bbox = BoundingBox.Empty;
            
            foreach (var geometry in geometries)
            {
                hld_params.AddGeometry(geometry, "");
                //geometry.Transform(zTransform);
                allGeoB.Add(geometry.GetBoundingBox(true));
                if (geometry != null)
                {
                    var objBbox = geometry.GetBoundingBox(true);
                    bbox.Union(objBbox);
                }
            }
            var box = new Box(bbox);
            //**** GET BLOCK BASE SURFACE ****//
            var xBox = box.X;
            var yBox = box.Y;
            var zBox = box.Z;
            var pBox = box.Plane;
            Interval z = new Interval(zBox.T0, zBox.T0);
            Box surface = new Box(pBox, xBox, yBox, z);
            var result = new Make2dResult();
            var hld = HiddenLineDrawing.Compute(hld_params, true);
            List<Curve> visMake2dCrvs = new List<Curve>();
            List<Curve> hidMake2dCrvs = new List<Curve>();
            var vis = HiddenLineDrawingSegment.Visibility.Visible;
            var hid = HiddenLineDrawingSegment.Visibility.Hidden;
            var un = HiddenLineDrawingSegment.Visibility.Unset;
            var h_attribs = new ObjectAttributes { Name = "H", LayerIndex = 1, LinetypeIndex = 6 };
            var v_attribs = new ObjectAttributes { Name = "V" };
            for (int i = 0; i < hld.Segments.Count(); i++)
            {
                if (hld.Segments.ElementAt(i).SegmentVisibility == vis || hld.Segments.ElementAt(i).SegmentVisibility == un) visMake2dCrvs.Add(hld.Segments.ElementAt(i).CurveGeometry);
                if (hld.Segments.ElementAt(i).SegmentVisibility == hid) hidMake2dCrvs.Add(hld.Segments.ElementAt(i).CurveGeometry);
            }
            List<Curve> projectedVisCrvs = new List<Curve>();
            List<Curve> projectedHidCrvs = new List<Curve>();
            for (int i = 0; i < visMake2dCrvs.Count; i++)
            {
                var projectCurve = Curve.ProjectToPlane(visMake2dCrvs[i], pBox);
                projectedVisCrvs.Add(projectCurve);
            }
            for (int i = 0; i < hidMake2dCrvs.Count; i++)
            {
                var projectCurve = Curve.ProjectToPlane(hidMake2dCrvs[i], pBox);
                projectedHidCrvs.Add(projectCurve);
            }
            var boundingboxCrvs = Make2DUtils.boundigboxCurve(projectedVisCrvs);
            var vec = surface.Center - boundingboxCrvs.Center;
            Transform trans = Transform.Translation(vec);
            foreach (var curve in projectedVisCrvs)
            {
                curve.Transform(trans);
                Curve crv;
                crv = curve.DuplicateCurve();
                crv = Curve.ProjectToPlane(crv, Plane.WorldXY);
                projectedVisibleCurves.Add(crv);
            }
            foreach (var curve in projectedHidCrvs)
            {
                curve.Transform(trans);
                Curve crv;
                crv = curve.DuplicateCurve();
                crv = Curve.ProjectToPlane(crv, Plane.WorldXY);
                projectedHiddeCurves.Add(crv);
            }

            result.curveVis = projectedVisibleCurves;
            result.curveHid = projectedHiddeCurves;
            return result;
        }


        public void RemoveDuplicateCurves(List<Curve> curves)
        {
            double tolerance = RhinoDoc.ActiveDoc.ModelAbsoluteTolerance;
            List<Curve> uniqueCurves = new List<Curve>();

            for (int i = 0; i < curves.Count; i++)
            {
                Curve currentCurve = curves[i];
                bool isDuplicate = false;
                // Compare current curve with all unique curves
                foreach (Curve uniqueCurve in uniqueCurves)
                {
                    // Check if curves have the same start and end points (within tolerance)
                    if ((currentCurve.PointAtStart.EpsilonEquals(uniqueCurve.PointAtStart, tolerance) &&
                         currentCurve.PointAtEnd.EpsilonEquals(uniqueCurve.PointAtEnd, tolerance)) ||
                        (currentCurve.PointAtStart.EpsilonEquals(uniqueCurve.PointAtEnd, tolerance) &&
                         currentCurve.PointAtEnd.EpsilonEquals(uniqueCurve.PointAtStart, tolerance)))
                    {
                        // Curves are considered duplicates
                        isDuplicate = true;
                        break;
                    }
                }

                // If it's not a duplicate, add it to the unique curves list
                if (!isDuplicate)
                {
                    uniqueCurves.Add(currentCurve);
                }
            }

            // Replace the original curve list with the unique ones
            curves.Clear();
            curves.AddRange(uniqueCurves);

        }

        public void RemoveSmallCurvesUnderLarger(List<Curve> curves)
        {
            double tolerance = RhinoDoc.ActiveDoc.ModelAbsoluteTolerance;
            List<Curve> curvesToKeep = new List<Curve>();

            for (int i = 0; i < curves.Count; i++)
            {
                Curve currentCurve = curves[i];
                bool isSmallerCurve = false;

                for (int j = 0; j < curves.Count; j++)
                {
                    if (i == j) continue; // Skip comparing the curve with itself

                    Curve compareCurve = curves[j];

                    // If the current curve is shorter in length, check for containment
                    if (currentCurve.GetLength() < compareCurve.GetLength())
                    {
                        // Get parameters along the smaller curve
                        double[] parameters = currentCurve.DivideByCount(10, true); // Divide the smaller curve into 10 segments

                        int pointsOnCurve = 0;
                        foreach (var param in parameters)
                        {
                            Point3d samplePoint = currentCurve.PointAt(param); // Get the actual point at the parameter

                            double paramOnLarger;
                            if (compareCurve.ClosestPoint(samplePoint, out paramOnLarger, tolerance))
                            {
                                Point3d closestPointOnLarger = compareCurve.PointAt(paramOnLarger);

                                // Check if the point on the smaller curve is within tolerance of the point on the larger curve
                                if (samplePoint.DistanceTo(closestPointOnLarger) <= tolerance)
                                {
                                    pointsOnCurve++;
                                }
                            }
                        }

                        // If 80% or more of the points lie on the larger curve, mark the smaller curve as contained
                        if (pointsOnCurve >= parameters.Length * 0.8)
                        {
                            isSmallerCurve = true;
                            break;
                        }
                    }
                }

                // If the current curve is not contained within another curve, keep it
                if (!isSmallerCurve)
                {
                    curvesToKeep.Add(currentCurve);
                }
            }

            // Replace the original curve list with only the unique, non-contained curves
            curves.Clear();
            curves.AddRange(curvesToKeep);

            RhinoApp.WriteLine($"Removed smaller curves. Remaining curves: {curves.Count}");
        }
    }
    /// <summary>
    /// Specifies the results of Make2D Method.
    /// </summary>
    public class Make2dResult
    {
        public List<Curve> curveVis { get; set; } = new List<Curve>();
        public List<Curve> curveHid { get; set; } = new List<Curve>();
    }
 

}


is it possible to modify this code to get 2d blocks and do the same thing as it doese for 3d blocks now?
whithoute messing around with the current code and its functunality just adding this functionality to it too.