/* ==============================================================================
 * 功能描述：RevitCoreContext  
 * 创 建 者：Garrett
 * 创建日期：2019/6/27 11:10:20
 * ==============================================================================*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Mime;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Autodesk.Revit;
using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.DB;
using Autodesk.RevitAddIns;

namespace ExportStart
{
    public class RevitCoreContext
    {
        // 此路径为动态反射搜索路径 、 此路径可为任意路径（只要路径下有RevitNET 所需依赖项即可，完整依赖项可在 Naviswork 2016 下面找到）

        static readonly string[] Searchs = RevitProductUtility.GetAllInstalledRevitProducts().Where(t => t.Name == "Revit 2017").Select(x => x.InstallLocation).ToArray();

        static readonly object lockobj = new object();

        static RevitCoreContext _instance;

        private Product _product;

        public Application Application { get => _product.Application; }

        public static RevitCoreContext Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (lockobj)
                    {
                        if (_instance == null)
                        {
                            _instance = new RevitCoreContext();
                        }
                    }
                }

                return _instance;
            }
        }

        static RevitCoreContext()
        {
            AddEnvironmentPaths(Searchs);

            AppDomain.CurrentDomain.AssemblyResolve += OnAssemblyResolve;
        }

        public void Run()
        {
            _product = Product.GetInstalledProduct();

            var clientId = new ClientApplicationId(Guid.NewGuid(), "DotNet", "BIMAPI");

            // I am authorized by Autodesk to use this UI-less functionality. 必须是此字符串。 Autodesk 规定的.

            _product.Init(clientId, "I am authorized by Autodesk to use this UI-less functionality.");
        }

        public void Stop()
        {
            _product?.Exit();
        }

        static void AddEnvironmentPaths(params string[] paths)
        {
            var path = new[] { Environment.GetEnvironmentVariable("PATH") ?? string.Empty };

            var newPath = string.Join(System.IO.Path.PathSeparator.ToString(), path.Concat(paths));

            Environment.SetEnvironmentVariable("PATH", newPath);
        }

        private static Assembly OnAssemblyResolve(object sender, ResolveEventArgs args)
        {
            var assemblyName = new AssemblyName(args.Name);

            foreach (var item in Searchs)
            {
                var file = string.Format("{0}.dll", System.IO.Path.Combine(item, assemblyName.Name));

                if (File.Exists(file))
                {
                    NeedAssemblys.Add(assemblyName.Name);
                    return Assembly.LoadFile(file);
                }
            }

            return args.RequestingAssembly;
        }
        public static List<string> NeedAssemblys = new List<string>();

        public static void PrintAllAssemblys()
        {
            string str = string.Join("\r\n", NeedAssemblys);
            Console.WriteLine(str);
        }
    }
}
