using AspectCore.Extensions.Reflection;
using Microsoft.AspNetCore.Hosting;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
using TEAMModelOS.SDK.Context.Attributes.Azure;

namespace TEAMModelOS.SDK.Helper.Common.ReflectorExtensions
{
    public static class ReflectorExtensions
    {
        public static T GetPropertyValue<T>(this object obj, string name, BindingFlags bindingFlags) where T : class
        {
            var chProperty = obj.GetType().GetTypeInfo().GetProperty(name, bindingFlags);
            var chReflector = chProperty.GetReflector();
            var value = chReflector.GetValue(obj) as T;

            return value;
        }

        public static Tuple<T, FieldInfo> GetFieldValue<T>(this object obj, string name, BindingFlags bindingFlags) where T : class
        {
            var chField = obj.GetType().GetTypeInfo().GetField(name, bindingFlags);
            var chReflector = chField.GetReflector();
            var value = chReflector.GetValue(obj) as T;

            return Tuple.Create(value, chField);
        }

        public static T GetFieldValue<T>(this Type type, string name, BindingFlags bindingFlags) where T : class
        {
            var chField = type.GetTypeInfo().GetField(name, bindingFlags);
            var chReflector = chField.GetReflector();
            var value = chReflector.GetValue(null) as T;
            return value;
        }

        /// <summary>
        /// 获取T类型属性标记的类集合
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static List<Type> GetAllTypeAsAttribute<T>(string[] ScanModel)
        {
            Type attr = typeof(T);
            string currentDirectory = Path.GetDirectoryName(attr.Assembly.Location);
            List<Type> types = new List<Type>();
            if (ScanModel != null)
            {
                foreach (var model in ScanModel)
                {
                    Assembly assembly = Assembly.LoadFrom(currentDirectory + "\\" + model + ".dll");
                    //  Assembly assembly = Assembly.GetCallingAssembly(); 
                    var TypeInModel = from t in assembly.GetTypes()
                                      let attributes = t.GetCustomAttributes(attr, true)
                                      where attributes != null && attributes.Length > 0
                                      select t;
                    types.AddRange(TypeInModel);
                }
            }
            return types;
        }
    }
}
