DesignScriptEntity
using Autodesk.DesignScript.Geometry.Core;
using Autodesk.DesignScript.Geometry.Properties;
using Autodesk.DesignScript.Interfaces;
using Autodesk.DesignScript.Runtime;
using DynamoServices;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Autodesk.DesignScript.Geometry
{
    [SupressImportIntoVM]
    public abstract class DesignScriptEntity : IDisposable
    {
        private IDesignScriptEntity mEntity;
        protected Func<IDesignScriptEntity> mConstructor;
        private int mRefCount = 1;
        private const double AsmModelerUpperExtent = 10000;
        private const double AsmModelerLowerExtent = 0.0001;
        [SupressImportIntoVM]
        public EntityTags Tags = new EntityTags(null, null);
        private int? mHashCode;
        internal bool IsDisposed {
            get {
                if (mEntity != null)
                    return mRefCount <= 0;
                return true;
            }
        }
        internal virtual IDesignScriptEntity HostImpl {
            get {
                if (mEntity == null && mConstructor != null)
                    InitEntity(mConstructor());
                return mEntity;
            }
        }
        public static double scaleFactor => HostFactory.Instance.ScaleFactor;
        internal T Track<T>(T childGeometry) where T : DesignScriptEntity
        {
            childGeometry.Tags.Parent = this;
            return childGeometry;
        }
        internal IEnumerable<T> Track<T>(IEnumerable<T> childGeometries) where T : DesignScriptEntity
        {
            return from x in childGeometries
            select Track(x);
        }
        internal T[] Track<T>(T[] childGeometries) where T : DesignScriptEntity
        {
            return (from x in childGeometries
            select Track(x)).ToArray();
        }
        internal DesignScriptEntity(Func<IDesignScriptEntity> constructor)
        {
            mConstructor = constructor;
        }
        internal DesignScriptEntity(IDesignScriptEntity entity, bool persist = true)
        {
            InitEntity(entity);
        }
        internal void InitEntity(IDesignScriptEntity entity)
        {
            if (entity == null)
                throw new ArgumentNullException("host", Resources.NullIDesignScriptEntityException);
            if (entity.get_Owner() != null)
                throw new ArgumentException(Resources.OwnerExistingException, "host");
            mEntity = entity;
            mEntity.SetOwner((object)this);
        }
        public void Dispose()
        {
            if (Application.Instance.IsExecuting)
                DisposeDisplayable();
            ReleaseEntity();
        }
        protected virtual void DisposeDisplayable()
        {
        }
        ~DesignScriptEntity()
        {
            Dispose(true);
        }
        internal void RetainEntity()
        {
            mRefCount++;
        }
        internal void ReleaseEntity()
        {
            bool num = mRefCount == 1;
            mRefCount--;
            if (num)
                Dispose(true);
        }
        protected virtual void Dispose(bool disposing)
        {
            if (disposing) {
                if (mRefCount <= 0) {
                    mRefCount = 0;
                    if (mEntity != null) {
                        ((IDisposable)mEntity).Dispose();
                        mEntity = null;
                        GC.SuppressFinalize(this);
                    }
                }
            } else {
                mEntity = null;
                mConstructor = null;
            }
        }
        public override string ToString()
        {
            return ((object)mEntity).ToString();
        }
        public sealed override int GetHashCode()
        {
            if (!mHashCode.HasValue)
                mHashCode = ComputeHashCode();
            return mHashCode.Value;
        }
        public sealed override bool Equals(object obj)
        {
            if (this == obj)
                return true;
            DesignScriptEntity designScriptEntity = obj as DesignScriptEntity;
            if (designScriptEntity == null)
                return false;
            return Equals(designScriptEntity);
        }
        public void Tessellate(IRenderPackage package, TessellationParameters parameters)
        {
            IGraphicItem val = mEntity as IGraphicItem;
            if (val != null) {
                parameters.set_ScaleFactor(scaleFactor);
                val.Tessellate(package, parameters);
            }
        }
        private static Tuple<double, double> recommendedScaleFactor(double input)
        {
            double y = 0;
            double num = input / scaleFactor;
            if (num >= 10000) {
                double num2 = Math.Log10(input / 10000);
                if (num2 % 1 == 0)
                    num2 += 1;
                y = Math.Ceiling(num2);
            } else if (num <= 0.0001) {
                double num3 = Math.Log10(input / 0.0001);
                if (num3 % 1 == 0)
                    num3 -= 1;
                y = Math.Floor(num3);
            }
            double num4 = Math.Pow(10, y);
            return new Tuple<double, double>(num4 * 0.0001, num4 * 10000);
        }
        protected static void CheckArgsForAsmExtents(double input)
        {
            if (input / scaleFactor >= 10000) {
                Tuple<double, double> tuple = recommendedScaleFactor(input);
                string empty = string.Empty;
                empty = ((!(tuple.Item2 > 100000000)) ? string.Format(Resources.UpperModelerExtentExceeded, tuple.Item1, tuple.Item2) : Resources.ModelerExtentsExceeded);
                LogWarningMessageEvents.OnLogWarningMessage(empty);
            }
        }
        protected virtual bool Equals(DesignScriptEntity dsentity)
        {
            if (mEntity == null)
                return false;
            if (mEntity == dsentity.mEntity)
                return true;
            return ((object)mEntity).GetHashCode() == ((object)dsentity.mEntity).GetHashCode();
        }
        protected virtual int ComputeHashCode()
        {
            int num = (mEntity != null) ? ((object)mEntity).GetHashCode() : 0;
            if (num != 0)
                return num;
            return base.GetHashCode();
        }
    }
}
            