using log4net;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using VIZ.Package.Domain;
using VIZ.Package.Plugin;

namespace VIZ.Package.Service
{
    /// <summary>
    /// 插件服务
    /// </summary>
    public class PluginService
    {
        /// <summary>
        /// 日志
        /// </summary>
        private static ILog log = LogManager.GetLogger(typeof(PluginService));

        /// <summary>
        /// 包装插件前缀
        /// </summary>
        public const string PLUGIN_ASSEMBLY_PREFIX = "VIZ.";

        /// <summary>
        /// 加载插件信息集合
        /// </summary>
        /// <returns>插件信息集合</returns>
        public List<PluginInfo> LoadPluginInfos()
        {
            List<PluginInfo> list = new List<PluginInfo>();

            string[] files = System.IO.Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory);

            Type pluginLifeCycleType = typeof(IPluginLifeCycle);

            foreach (string file in files)
            {
                string fileName = System.IO.Path.GetFileName(file);

                if (!fileName.StartsWith(PLUGIN_ASSEMBLY_PREFIX) || !fileName.EndsWith(".dll"))
                    continue;

                Assembly assembly = Assembly.LoadFile(file);
                string version = assembly.GetCustomAttribute<AssemblyVersionAttribute>()?.Version;
                Type[] types = assembly.GetTypes();

                foreach (Type type in types)
                {
                    if (!type.IsClass)
                        continue;

                    if (!pluginLifeCycleType.IsAssignableFrom(type))
                        continue;

                    IPluginLifeCycle lifeCycle = type.Assembly.CreateInstance(type.FullName) as IPluginLifeCycle;
                    if (lifeCycle == null)
                    {
                        log.Error($"init plugin type: {type.FullName} error.");
                        continue;
                    }

                    PluginInfo info = lifeCycle.Register();
                    list.Add(info);
                }
            }

            return list;
        }
    }
}
