using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Mall.Common.Plugin
{
    /// <summary>
    /// 反射映射
    /// </summary>
    public static class ReflectionMapperHelper
    {
        /// <summary>
        /// 类型映射
        /// </summary>
        /// <typeparam name="TOut">转换目标</typeparam>
        /// <param name="source">目标源</param>
        /// <returns></returns>
        public static TOut RefMapperTo<TOut>(this object source)
        {
            if (source == null)
            {
                return default(TOut);
            }
            else
            {
                Type sourceType = source.GetType();
                TOut tOut = Activator.CreateInstance<TOut>();
                Type outType = tOut.GetType();
                foreach (var itemOut in outType.GetProperties())
                {
                    foreach (var itemIn in sourceType.GetProperties())
                    {
                        if (itemOut.Name.ToLower().Equals(itemIn.Name.ToLower()) && itemOut.PropertyType == itemIn.PropertyType)
                        {
                            itemOut.SetValue(tOut, itemIn.GetValue(source));
                            break;
                        }
                    }
                }
                foreach (var itemOut in outType.GetFields())
                {
                    foreach (var itemIn in sourceType.GetFields())
                    {
                        if (itemOut.Name.ToLower().Equals(itemIn.Name.ToLower()) && itemOut.FieldType == itemIn.FieldType)
                        {
                            itemOut.SetValue(tOut, itemIn.GetValue(source));
                            break;
                        }
                    }
                }
                return tOut;
            }
        }

        /// <summary>
        /// 集合列表类型映射
        /// </summary>
        /// <typeparam name="TOut">转换目标</typeparam>
        /// <param name="sourceList">目标源</param>
        /// <returns></returns>
        public static List<TOut> RefMapperToList<TOut>(this IEnumerable sourceList)
        {
            List<TOut> outList = new List<TOut>();
            foreach (var source in sourceList)
            {
                Type sourceType = source.GetType();
                TOut tOut = Activator.CreateInstance<TOut>();
                Type outType = tOut.GetType();
                foreach (var itemOut in outType.GetProperties())
                {
                    foreach (var itemIn in sourceType.GetProperties())
                    {
                        if (itemOut.Name.ToLower().Equals(itemIn.Name.ToLower()) && itemOut.PropertyType == itemIn.PropertyType)
                        {
                            itemOut.SetValue(tOut, itemIn.GetValue(source));
                            break;
                        }
                    }
                }
                foreach (var itemOut in outType.GetFields())
                {
                    foreach (var itemIn in sourceType.GetFields())
                    {
                        if (itemOut.Name.ToLower().Equals(itemIn.Name.ToLower()) && itemOut.FieldType == itemIn.FieldType)
                        {
                            itemOut.SetValue(tOut, itemIn.GetValue(source));
                            break;
                        }
                    }
                }
                outList.Add(tOut);
            }

            return outList;
        }
    }
}
