using System;
using Autodesk.Navisworks.Api;

namespace NavisworksTransport.Utils
{
    /// <summary>
    /// Navisworks单位转换工具类
    /// 提供统一的单位转换功能，避免代码重复
    /// 
    /// 性能优化：缓存转换系数，避免重复访问API
    /// </summary>
    public static class UnitsConverter
    {
        // 缓存字段 - 使用 NaN 作为初始值，避免默认值掩盖错误
        private static double _cachedUnitsToMetersFactor = double.NaN;
        private static double _cachedMetersToUnitsFactor = double.NaN;
        private static Units _cachedUnits = Units.Meters;

        /// <summary>
        /// 清除转换系数缓存（在单位变化时调用）
        /// </summary>
        public static void ClearCache()
        {
            _cachedUnitsToMetersFactor = double.NaN;
            _cachedMetersToUnitsFactor = double.NaN;
        }

        /// <summary>
        /// 检查缓存是否有效（已设置且单位未变化）
        /// </summary>
        private static bool IsCacheValid()
        {
            // 从未设置过（NaN）
            if (double.IsNaN(_cachedUnitsToMetersFactor) || double.IsNaN(_cachedMetersToUnitsFactor))
                return false;
            
            try
            {
                var currentUnits = Application.ActiveDocument?.Units ?? Units.Meters;
                return currentUnits == _cachedUnits;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 更新缓存
        /// </summary>
        private static void UpdateCache()
        {
            try
            {
                var currentUnits = Application.ActiveDocument?.Units ?? Units.Meters;
                
                // 如果单位变化，更新缓存
                if (currentUnits != _cachedUnits)
                {
                    _cachedUnits = currentUnits;
                    _cachedUnitsToMetersFactor = GetUnitsToMetersConversionFactor(currentUnits);
                    _cachedMetersToUnitsFactor = GetMetersToUnitsConversionFactor(currentUnits);
                }
            }
            catch
            {
                // 主路径异常时，用显式文档单位兜底（副实例/文档加载瞬间 ActiveDocument.Units 访问可能抛，
                // 显式访问通常可用；避免缓存长期 NaN 导致尺寸/路径长度全错）
                try
                {
                    var doc = Application.ActiveDocument;
                    if (doc != null)
                    {
                        var currentUnits = doc.Units;
                        _cachedUnits = currentUnits;
                        _cachedUnitsToMetersFactor = GetUnitsToMetersConversionFactor(currentUnits);
                        _cachedMetersToUnitsFactor = GetMetersToUnitsConversionFactor(currentUnits);
                    }
                }
                catch
                {
                    // 仍失败则保留上次有效值（或 NaN 暴露错误）
                }
            }
        }

        /// <summary>
        /// 获取Navisworks文档单位转换为米的系数
        /// </summary>
        /// <returns>转换系数（文档单位转换为米）</returns>
        public static double GetUnitsToMetersConversionFactor()
        {
            UpdateCache();

            // 缓存异常（NaN，副实例/文档加载瞬间）时用显式文档单位兜底
            if (double.IsNaN(_cachedUnitsToMetersFactor))
            {
                var doc = Application.ActiveDocument;
                if (doc != null)
                {
                    return GetUnitsToMetersConversionFactor(doc.Units);
                }
            }

            return _cachedUnitsToMetersFactor;
        }

        /// <summary>
        /// 获取指定单位转换为米的系数
        /// </summary>
        /// <param name="units">单位类型</param>
        /// <returns>转换系数（指定单位转换为米）</returns>
        public static double GetUnitsToMetersConversionFactor(Units units)
        {
            switch (units)
            {
                case Units.Millimeters:
                    return 0.001;
                case Units.Centimeters:
                    return 0.01;
                case Units.Meters:
                    return 1.0;
                case Units.Inches:
                    return 0.0254;
                case Units.Feet:
                    return 0.3048;
                case Units.Kilometers:
                    return 1000.0;
                case Units.Micrometers:
                    return 0.000001;
                case Units.Microinches:
                    return 0.0000000254;
                case Units.Mils:
                    return 0.0000254;
                case Units.Yards:
                    return 0.9144;
                case Units.Miles:
                    return 1609.43;
                default:
                    return 1.0;
            }
        }

        /// <summary>
        /// <summary>
        /// 获取米转换为文档单位的系数
        /// </summary>
        /// <returns>转换系数（米转换为文档单位）</returns>
        public static double GetMetersToUnitsConversionFactor()
        {
            UpdateCache();

            // 缓存异常（NaN，副实例/文档加载瞬间）时用显式文档单位兜底
            if (double.IsNaN(_cachedMetersToUnitsFactor))
            {
                var doc = Application.ActiveDocument;
                if (doc != null)
                {
                    return GetMetersToUnitsConversionFactor(doc.Units);
                }
            }

            return _cachedMetersToUnitsFactor;
        }

        /// <summary>
        /// 获取米转换为指定单位的系数
        /// </summary>
        /// <param name="units">单位类型</param>
        /// <returns>转换系数（米转换为指定单位）</returns>
        public static double GetMetersToUnitsConversionFactor(Units units)
        {
            switch (units)
            {
                case Units.Millimeters:
                    return 1000.0; // 1米 = 1000毫米
                case Units.Centimeters:
                    return 100.0; // 1米 = 100厘米
                case Units.Meters:
                    return 1.0; // 1米 = 1米
                case Units.Inches:
                    return 39.37; // 1米 = 39.37英寸
                case Units.Feet:
                    return 3.281; // 1米 = 3.281英尺
                case Units.Kilometers:
                    return 0.001; // 1米 = 0.001公里
                case Units.Micrometers:
                    return 1000000.0; // 1米 = 1000000微米
                case Units.Microinches:
                    return 39370078.74; // 1米 = 39370078.74微英寸
                case Units.Mils:
                    return 39370.08; // 1米 = 39370.08密尔
                case Units.Yards:
                    return 1.094; // 1米 = 1.094码
                case Units.Miles:
                    return 0.000621; // 1米 = 0.000621英里
                default:
                    return 1.0;
            }
        }

        /// <summary>
        /// 将距离从文档单位转换为米
        /// </summary>
        /// <param name="distance">距离（文档单位）</param>
        /// <returns>距离（米）</returns>
        public static double ConvertToMeters(double distance)
        {
            return distance * GetUnitsToMetersConversionFactor();
        }

        /// <summary>
        /// 将距离从米转换为文档单位
        /// </summary>
        /// <param name="distanceInMeters">距离（米）</param>
        /// <returns>距离（文档单位）</returns>
        public static double ConvertFromMeters(double distanceInMeters)
        {
            return distanceInMeters * GetMetersToUnitsConversionFactor();
        }
    }
}
