/*-------------------------------------------------------------------------
 * 功能描述：GeometryElementExtension
 * 作者：xulisong
 * 创建时间： 2019/6/26 16:17:26
 * 版本号：v1.0
 *  -------------------------------------------------------------------------*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Autodesk.Revit.DB;

namespace RevitToJBim.Extension
{
    public static class  GeometryElementExtension
    {
        /// <summary>
        /// 查找原始的几何对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="geoElement"></param>
        /// <returns></returns>
        public static List<T> GetGeometryOriginalObjects<T>(this GeometryElement geoElement) where T : GeometryObject
        {
            List<T> listRtn = new List<T>();
            List<GeometryElement> useElements = new List<GeometryElement>() { geoElement };
            for (int i = 0; i < useElements.Count; i++)
            {
                var useGeoElement = useElements[i];
                foreach (var geoObject in useGeoElement)
                {
                    //系统族、相交切割后的外部族
                    if (geoObject is T)
                    {
                        listRtn.Add(geoObject as T);
                    }
                    else if (geoObject is GeometryInstance)
                    {
                        var childElment = (geoObject as GeometryInstance).GetInstanceGeometry();
                        if (childElment != null)
                        {
                            useElements.Add(childElment);
                        }
                    }
                    else if (geoObject is GeometryElement)
                    {
                        useElements.Add(geoObject as GeometryElement);
                    }
                }
            }
            return listRtn;
        }
        public static List<T> GetGeometryObjects<T>(this GeometryElement geoElement) where T : GeometryObject
        {
            List<T> listRtn = geoElement.GetGeometryOriginalObjects<T>();
            if (listRtn.Count == 0)
            {
                //计算为几何信息复制，可能引用相关有问题
                var geoElementNew = geoElement.GetTransformed(Transform.Identity);
                listRtn = geoElementNew.GetGeometryOriginalObjects<T>();
            }
            return listRtn;
        }

        /// <summary>
        /// 获取指定元素的几何描述
        /// </summary>
        /// <param name="element"></param>
        /// <param name="visibleObj"></param>
        /// <param name="view"></param>
        /// <returns></returns>
        public static GeometryElement GetGeometryElement(this Element element, bool visibleObj = false, View view = null)
        {
            var options = new Options();
            options.ComputeReferences = true;
            options.IncludeNonVisibleObjects = visibleObj;
            if (view == null)
            {
                options.DetailLevel = ViewDetailLevel.Fine;
            }
            else
            {
                options.View = view;
            }

            return element.get_Geometry(options);
        }

        /// <summary>
        /// 获取几何Solid
        /// </summary>
        /// <param name="elem"></param>
        /// <param name="view"></param>
        /// <param name="visibleObj"></param>
        /// <returns></returns>
        public static List<Solid> GetSolids(this Element elem, View view = null, bool visibleObj = false)
        {
            var geoElement = elem.GetGeometryElement(visibleObj, view);
            return geoElement.GetGeometryObjects<Solid>();
        }
        /// <summary>
        /// 获取几何Solid
        /// </summary>
        /// <param name="elem"></param>
        /// <param name="view"></param>
        /// <param name="visibleObj"></param>
        /// <returns></returns>
        public static List<T> GetGeometryObjects<T>(this Element elem, View view = null, bool visibleObj = false) where T : GeometryObject
        {
            var geoElement = elem.GetGeometryElement(visibleObj, view);
            return geoElement.GetGeometryObjects<T>();
        }
    }
}
