using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Reflection;
using XKRS.Common.Model.Helper;

namespace XKRS.Common.Factory
{
    public static class FactoryHelper
    {
        const string DLLPATTERN = "XKRS.*.dll";
        //readonly指示只能在声明期间或在同一个类的构造函数中向字段赋值
        //可以在字段声明和构造函数中多次分配和重新分配只读字段。
        //构造函数退出后，不能分配 readonly 字段。
        private static readonly string[] DLLPATTERNS = { "XKRS." };

        private static List<Type> types = new List<Type>();
        public static List<Type> TYPES
        {
            get
            {
                if (types.Count <= 0)
                {
                    types = GetAttributeType<DeviceAttribute>().Values.ToList();
                }
                return types;
            }
        }
       
        public static Dictionary<T, Type> GetAttributeType<T>() where T : Attribute
        {
            Dictionary<T, Type> attrTyprDict = new Dictionary<T, Type>();//创建一个键值对集合
            var dllFiles = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory)
                .GetFiles("*.dll")
                .Where(fi => DLLPATTERNS.Any(pattern => fi.Name.StartsWith(pattern)))
                .Select(u =>
                {
                    try
                    {
                        return u.FullName;//获取完整目录
                    }
                    catch { }
                    return string.Empty;//返回一个只读的空字符串，
                })
                .Where(s => !string.IsNullOrEmpty(s))
                .ToList();
            dllFiles.ForEach(f =>
            {
                try
                {
                    Assembly assm = Assembly.LoadFrom(f);
                    if (assm != null)
                    {
                        assm.GetTypes().ToList().ForEach(t =>
                        {
                            T attr = t.GetCustomAttribute<T>();
                            if (attr != null)
                            {
                                attrTyprDict[attr] = t;
                            }
                        });
                    }
                }
                catch(Exception)
                {

                }
            });
            return attrTyprDict;
        }

        public static Type GetTypeByAttributeTypeName(string attrTypeName, EnumHelper.DeviceAttributeType attrType)
        {
            Type type = TYPES.FirstOrDefault(t =>
            {
                DeviceAttribute attr = t.GetCustomAttribute<DeviceAttribute>();
                return attr != null && attr.TypeCode == attrTypeName && attr.AttrType == attrType;
            });
            return type;
        }
    }
}
