GeometryExtension
using Autodesk.DesignScript.Interfaces;
using Autodesk.DesignScript.Runtime;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
namespace Autodesk.DesignScript.Geometry
{
    [SupressImportIntoVM]
    public static class GeometryExtension
    {
        internal static string DoublePrintFormat = "F3";
        public static readonly double PI = 3.141592653589793;
        public static bool LessThanOrEquals(double x, double y, double tolerance = 1E-06)
        {
            if (Equals(x, y, tolerance))
                return true;
            if (x < y)
                return true;
            return false;
        }
        public static bool Equals(double x, double y, double tolerance = 1E-06)
        {
            return Math.Abs(x - y) < tolerance;
        }
        public static bool EqualsTo(this double thisValue, double value)
        {
            return Equals(thisValue, value, 1E-06);
        }
        public static bool LessThanOrEqualTo(this double thisValue, double value)
        {
            if (!(thisValue < value))
                return Equals(thisValue, value, 1E-06);
            return true;
        }
        [SupressImportIntoVM]
        internal static bool EqualsTo(this IPointEntity thisValue, IPointEntity value)
        {
            if (thisValue == value)
                return true;
            if (thisValue == null || value == null)
                return false;
            if (Equals(thisValue.get_X(), value.get_X(), 1E-06) && Equals(thisValue.get_Y(), value.get_Y(), 1E-06))
                return Equals(thisValue.get_Z(), value.get_Z(), 1E-06);
            return false;
        }
        [SupressImportIntoVM]
        public static bool AreCoincident(this IPointEntity[] pts)
        {
            if (pts == null)
                return true;
            int num = pts.Length;
            for (int i = 0; i < num - 1; i++) {
                if (!pts[i].EqualsTo(pts[i + 1]))
                    return false;
            }
            return true;
        }
        public static double DegreesToRadians(double deg)
        {
            return deg * PI / 180;
        }
        public static double RadiansToDegrees(double rad)
        {
            return rad * 180 / PI;
        }
        [SupressImportIntoVM]
        public static IPointEntity[][] ToPointEntityArray(this Point[][] points, bool checkRectangular = true)
        {
            if (points == null)
                return null;
            List<IPointEntity[]> list = new List<IPointEntity[]>();
            int num = -1;
            for (int i = 0; i < points.Length; i++) {
                IPointEntity[] array = points[i].ConvertAll(GeometryExtension.ToEntity<Point, IPointEntity>);
                if (array != null && array.Length != 0) {
                    if (checkRectangular) {
                        if (num == -1)
                            num = array.Length;
                        if (num != array.Length)
                            return null;
                    }
                    list.Add(array);
                }
            }
            if (list.Count == 0)
                return null;
            return list.ToArray();
        }
        [SupressImportIntoVM]
        public static Point[][] ToPointArray(this IPointEntity[][] points, bool checkRectangular = true)
        {
            List<Point[]> list = new List<Point[]>();
            int num = -1;
            for (int i = 0; i < points.Length; i++) {
                Point[] array = points[i].ConvertAll((IPointEntity p) => p.ToPoint(false, null));
                if (array != null) {
                    if (checkRectangular) {
                        if (num == -1)
                            num = array.Length;
                        if (num != array.Length)
                            return null;
                    }
                    list.Add(array);
                }
            }
            return list.ToArray();
        }
        private static GeomClass ToGeometry<GeomClass, GeomEntity>(this GeomEntity host, bool persist = false, Geometry context = null) where GeomClass : Geometry where GeomEntity : IGeometryEntity
        {
            return Geometry.Wrap((object)host, persist, context) as GeomClass;
        }
        [SupressImportIntoVM]
        internal static GEOM[] ToArray<GEOM, ENTITY>(this ENTITY[] hosts, bool persist = true, Geometry context = null) where GEOM : Geometry where ENTITY : IGeometryEntity
        {
            if (hosts == null)
                return null;
            List<GEOM> list = new List<GEOM>();
            foreach (ENTITY val in hosts) {
                if (val != null) {
                    GEOM val2 = Geometry.Wrap((object)val, persist, context) as GEOM;
                    if (val2 != null)
                        list.Add(val2);
                }
            }
            return list.ToArray();
        }
        [SupressImportIntoVM]
        public static IDesignScriptEntity ToEntity(this DesignScriptEntity data)
        {
            return data.ToEntity<DesignScriptEntity, IDesignScriptEntity>();
        }
        [SupressImportIntoVM]
        internal static ENTITY ToEntity<GEOMETRY, ENTITY>(this GEOMETRY data) where GEOMETRY : DesignScriptEntity where ENTITY : IDesignScriptEntity
        {
            if (data == null)
                return default(ENTITY);
            return (ENTITY)(object)data.HostImpl;
        }
        [SupressImportIntoVM]
        public static ICurveEntity GetCurveEntity(Curve curve, bool checkClosed)
        {
            bool isClosed = curve.IsClosed;
            if ((checkClosed & isClosed) || (!checkClosed && !isClosed))
                return curve.CurveEntity;
            return null;
        }
        internal static bool IsDisposed<T>(this T obj) where T : DesignScriptEntity
        {
            return obj?.IsDisposed ?? true;
        }
        internal static bool IsDisposed<T>(this T[] obj) where T : DesignScriptEntity
        {
            if (obj == null)
                return true;
            for (int i = 0; i < obj.Length; i++) {
                if (obj[i].IsDisposed())
                    return true;
            }
            return false;
        }
        internal static bool IsDisposed<T>(this T[][] obj) where T : DesignScriptEntity
        {
            if (obj == null)
                return true;
            for (int i = 0; i < obj.Length; i++) {
                if (obj[i].IsDisposed())
                    return true;
            }
            return false;
        }
        internal static void DisposeObject(this IDisposable obj)
        {
            obj?.Dispose();
        }
        internal static void DisposeObject<T>(ref T obj) where T : DesignScriptEntity
        {
            if (obj != null) {
                obj.Dispose();
                if (obj.IsDisposed)
                    obj = null;
            }
        }
        internal static void DisposeObject<T>(ref T[] obj) where T : DesignScriptEntity
        {
            obj.ForEach(delegate(T item) {
                GeometryExtension.DisposeObject<T>(ref item);
            });
            if (obj.IsDisposed())
                obj = null;
        }
        internal static void DisposeObject<T>(ref T[][] obj) where T : DesignScriptEntity
        {
            obj.ForEach(delegate(T[] item) {
                GeometryExtension.DisposeObject<T>(ref item);
            });
            if (obj.IsDisposed())
                obj = null;
        }
        internal static void DisposeObject(this IDisposable[] obj)
        {
            obj.ForEach(DisposeObject);
        }
        internal static void DisposeObject(this IDisposable[][] obj)
        {
            obj.ForEach((Action<IDisposable>)DisposeObject);
        }
        public static void ForEach<T>(this T[] array, Action<T> action)
        {
            if (array != null) {
                foreach (T obj in array) {
                    action(obj);
                }
            }
        }
        public static void ForEach<T>(this T[][] array, Action<T> action)
        {
            if (array != null) {
                for (int i = 0; i < array.Length; i++) {
                    array[i].ForEach(action);
                }
            }
        }
        public static TOutput[] ConvertAll<TInput, TOutput>(this TInput[] array, Converter<TInput, TOutput> converter)
        {
            if (array == null)
                return null;
            List<TOutput> list = new List<TOutput>();
            foreach (TInput val in array) {
                if (val != null) {
                    TOutput val2 = converter(val);
                    if (val2 != null)
                        list.Add(val2);
                }
            }
            if (list.Count == 0)
                return null;
            return list.ToArray();
        }
        internal static Point[] CreatePoints(this IPointEntity[] points)
        {
            return points.ToArray<Point, IPointEntity>(false, (Geometry)null);
        }
        internal static Point ToPoint(this IPointEntity host, bool persist, Geometry context)
        {
            return host.ToGeometry<Point, IPointEntity>(persist, context);
        }
        internal static Curve ToCurve(this ICurveEntity host, bool persist, Geometry context)
        {
            return host.ToGeometry<Curve, ICurveEntity>(persist, context);
        }
        internal static Line ToLine(this ILineEntity host, bool persist, Geometry context)
        {
            return host.ToGeometry<Line, ILineEntity>(persist, context);
        }
        internal static Surface ToSurf(this ISurfaceEntity host, bool persist, Geometry context)
        {
            return host.ToGeometry<Surface, ISurfaceEntity>(persist, context);
        }
        internal static NurbsSurface ToNurbsSurf(this INurbsSurfaceEntity host, bool persist, Geometry context)
        {
            return host.ToGeometry<NurbsSurface, INurbsSurfaceEntity>(persist, context);
        }
        internal static Plane ToPlane(this IPlaneEntity host, bool persist, Geometry context)
        {
            return host.ToGeometry<Plane, IPlaneEntity>(persist, context);
        }
        internal static Solid ToSolid(this ISolidEntity host, bool persist, Geometry context)
        {
            return host.ToGeometry<Solid, ISolidEntity>(persist, context);
        }
        internal static bool ClipParamRange(ref double param)
        {
            if (param < 0) {
                param = 0;
                return true;
            }
            if (param > 1) {
                param = 1;
                return true;
            }
            return false;
        }
        public static string LocateFile(string fileName)
        {
            if (fileName == null)
                return null;
            IExecutionSession session = Application.Instance.Session;
            if (session != null) {
                string text = session.SearchFile(fileName);
                if (text != null)
                    return text;
            } else {
                string text2 = Path.Combine(Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath), fileName);
                if (text2 != null && File.Exists(text2))
                    return text2;
            }
            string[] array = (Environment.GetEnvironmentVariable("PATH") ?? "").Split(new char[1] {
                ';'
            });
            char[] trimChars = new char[1] {
                '"'
            };
            string[] array2 = array;
            for (int i = 0; i < array2.Length; i++) {
                string text3 = array2[i].Trim();
                if (!string.IsNullOrEmpty(text3)) {
                    text3 = text3.Trim(trimChars);
                    if (!string.IsNullOrEmpty(text3) && File.Exists(text3 = Path.Combine(text3, fileName)))
                        return Path.GetFullPath(text3);
                }
            }
            return fileName;
        }
    }
}