using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using ComApi = Autodesk.Navisworks.Api.Interop.ComApi;
using ComApiBridge = Autodesk.Navisworks.Api.ComApi.ComApiBridge;

namespace NavisworksTransport
{
    /// <summary>
    /// COM API 管理基类 - 提供标准化的COM对象管理模式
    /// 统一COM对象生命周期管理、异常处理和资源释放
    /// </summary>
    public abstract class ComApiBase : IDisposable
    {
        #region 字段和属性

        /// <summary>
        /// COM状态对象，通过统一管理器获取
        /// </summary>
        protected ComApi.InwOpState10 ComState
        {
            get { return ComStateManager.GetState(); }
        }

        /// <summary>
        /// 跟踪COM对象的集合，确保正确释放
        /// </summary>
        private readonly List<object> _trackedComObjects = new List<object>();

        /// <summary>
        /// 对象释放锁
        /// </summary>
        private readonly object _disposeLock = new object();

        /// <summary>
        /// 是否已释放标志
        /// </summary>
        private bool _disposed = false;

        #endregion

        #region COM对象管理方法

        /// <summary>
        /// 注册COM对象以便跟踪和自动释放
        /// </summary>
        /// <typeparam name="T">COM对象类型</typeparam>
        /// <param name="comObject">要跟踪的COM对象</param>
        /// <returns>注册的COM对象</returns>
        protected T TrackComObject<T>(T comObject) where T : class
        {
            if (comObject == null) return null;

            lock (_disposeLock)
            {
                if (!_disposed && Marshal.IsComObject(comObject))
                {
                    _trackedComObjects.Add(comObject);
                    LogManager.Debug($"[COM跟踪] 注册COM对象: {typeof(T).Name}，当前跟踪数量: {_trackedComObjects.Count}");
                }
            }

            return comObject;
        }

        /// <summary>
        /// 安全释放单个COM对象
        /// </summary>
        /// <param name="comObject">要释放的COM对象</param>
        /// <param name="objectName">对象名称（用于日志）</param>
        protected void SafeReleaseComObject(object comObject, string objectName = "未知COM对象")
        {
            if (comObject == null)
            {
                LogManager.Debug($"[COM释放] {objectName}为null，无需释放");
                return;
            }

            try
            {
                if (Marshal.IsComObject(comObject))
                {
                    Marshal.ReleaseComObject(comObject);
                    LogManager.Debug($"[COM释放] 成功释放{objectName}");
                }
                else
                {
                    LogManager.Debug($"[COM释放] {objectName}不是COM对象，跳过释放");
                }
            }
            catch (InvalidComObjectException)
            {
                LogManager.Debug($"[COM释放] {objectName}已无效，无需释放");
            }
            catch (Exception ex)
            {
                LogManager.Warning($"[COM释放] 释放{objectName}失败: {ex.Message}");
            }
            finally
            {
                // 从跟踪列表中移除
                lock (_disposeLock)
                {
                    _trackedComObjects.Remove(comObject);
                }
            }
        }

        /// <summary>
        /// 批量释放跟踪的COM对象
        /// </summary>
        protected void ReleaseAllTrackedComObjects()
        {
            lock (_disposeLock)
            {
                LogManager.Debug($"[COM批量释放] 开始释放 {_trackedComObjects.Count} 个跟踪的COM对象");

                var objectsToRelease = new List<object>(_trackedComObjects);
                _trackedComObjects.Clear();

                foreach (var comObject in objectsToRelease)
                {
                    try
                    {
                        if (comObject != null && Marshal.IsComObject(comObject))
                        {
                            Marshal.ReleaseComObject(comObject);
                        }
                    }
                    catch (Exception ex)
                    {
                        LogManager.Warning($"[COM批量释放] 释放跟踪对象失败: {ex.Message}");
                    }
                }

                LogManager.Debug("[COM批量释放] 完成所有跟踪COM对象的释放");
            }
        }

        /// <summary>
        /// 执行COM操作的安全包装方法
        /// </summary>
        /// <typeparam name="T">返回类型</typeparam>
        /// <param name="operation">要执行的操作</param>
        /// <param name="operationName">操作名称（用于日志）</param>
        /// <returns>操作结果</returns>
        /// <exception cref="COMException">COM操作失败时抛出</exception>
        protected T SafeComOperation<T>(Func<T> operation, string operationName = "COM操作")
        {
            try
            {
                LogManager.Debug($"[COM操作] 开始执行: {operationName}");
                var result = operation();
                LogManager.Debug($"[COM操作] 成功完成: {operationName}");
                return result;
            }
            catch (COMException comEx)
            {
                LogManager.Error($"[COM操作] COM异常 - {operationName}: {comEx.Message} (HRESULT: 0x{comEx.ErrorCode:X8})");
                throw;
            }
            catch (InvalidComObjectException)
            {
                LogManager.Error($"[COM操作] COM对象已无效 - {operationName}");
                throw;
            }
            catch (Exception ex)
            {
                LogManager.Error($"[COM操作] 一般异常 - {operationName}: {ex.Message}");
                throw;
            }
        }

        /// <summary>
        /// 执行无返回值COM操作的安全包装方法
        /// </summary>
        /// <param name="operation">要执行的操作</param>
        /// <param name="operationName">操作名称（用于日志）</param>
        /// <exception cref="COMException">COM操作失败时抛出</exception>
        protected void SafeComOperation(Action operation, string operationName = "COM操作")
        {
            SafeComOperation(() =>
            {
                operation();
                return true;
            }, operationName);
        }

        #endregion

        #region IDisposable 实现

        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// 释放资源的实际实现
        /// </summary>
        /// <param name="disposing">是否释放托管资源</param>
        protected virtual void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                if (disposing)
                {
                    try
                    {
                        LogManager.Debug($"[COM基类] 开始释放 {GetType().Name} 的资源");

                        // 释放所有跟踪的COM对象
                        ReleaseAllTrackedComObjects();

                        // 调用派生类的清理方法
                        OnDisposing();

                        LogManager.Debug($"[COM基类] 完成释放 {GetType().Name} 的资源");
                    }
                    catch (Exception ex)
                    {
                        LogManager.Error($"[COM基类] 释放 {GetType().Name} 资源时发生异常: {ex.Message}");
                    }
                }

                _disposed = true;
            }
        }

        /// <summary>
        /// 派生类可重写此方法进行特定的清理操作
        /// </summary>
        protected virtual void OnDisposing()
        {
            // 派生类可以重写此方法进行特定清理
        }

        /// <summary>
        /// 析构函数
        /// </summary>
        ~ComApiBase()
        {
            Dispose(false);
        }

        /// <summary>
        /// 检查对象是否已释放
        /// </summary>
        protected void ThrowIfDisposed()
        {
            if (_disposed)
            {
                throw new ObjectDisposedException(GetType().Name);
            }
        }

        #endregion
    }

    /// <summary>
    /// COM状态对象统一管理器
    /// </summary>
    public static class ComStateManager
    {
        private static ComApi.InwOpState10 _sharedState;
        private static readonly object _stateLock = new object();

        /// <summary>
        /// 获取COM状态对象（单例模式）
        /// </summary>
        /// <returns>COM状态对象</returns>
        public static ComApi.InwOpState10 GetState()
        {
            lock (_stateLock)
            {
                if (_sharedState == null)
                {
                    try
                    {
                        _sharedState = ComApiBridge.State;
                        LogManager.Debug("[COM状态管理] 初始化COM状态对象");
                    }
                    catch (Exception ex)
                    {
                        LogManager.Error($"[COM状态管理] 获取COM状态失败: {ex.Message}");
                        throw;
                    }
                }
                return _sharedState;
            }
        }

        /// <summary>
        /// 重置COM状态对象（仅在特殊情况下使用）
        /// </summary>
        public static void ResetState()
        {
            lock (_stateLock)
            {
                LogManager.Warning("[COM状态管理] 重置COM状态对象");
                _sharedState = null;
            }
        }

        /// <summary>
        /// 获取COM状态管理器状态信息
        /// </summary>
        /// <returns>状态信息</returns>
        public static string GetStatusInfo()
        {
            lock (_stateLock)
            {
                return $"COM状态管理器状态: {(_sharedState != null ? "已初始化" : "未初始化")}";
            }
        }
    }
}