using System;
using System.ComponentModel;
using System.Linq;
using System.Text;

namespace DPP_YH_Core.Extensions
{
    public static class ObjectExtension
    {
        public static string ToNewtonJsonStr(this object obj)
        {
            return Newtonsoft.Json.JsonConvert.SerializeObject(obj);
        }

        public static T ToJson<T>(this string obj)
        {
            return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(obj);
        }
        public static T To<T>(this Object @this)
        {
            if (@this != null)
            {
                Type targetType = typeof(T);

                if (@this.GetType() == targetType)
                {
                    return (T)@this;
                }

                TypeConverter converter = TypeDescriptor.GetConverter(@this);
                if (converter != null)
                {
                    if (converter.CanConvertTo(targetType))
                    {
                        return (T)converter.ConvertTo(@this, targetType);
                    }
                }

                converter = TypeDescriptor.GetConverter(targetType);
                if (converter != null)
                {
                    if (converter.CanConvertFrom(@this.GetType()))
                    {
                        return (T)converter.ConvertFrom(@this);
                    }
                }

                if (@this == DBNull.Value)
                {
                    return (T)(object)null;
                }
            }

            return (T)@this;
        }

        public static object To(this Object @this, Type type)
        {
            if (@this != null)
            {
                Type targetType = type;

                if (@this.GetType() == targetType)
                {
                    return @this;
                }

                TypeConverter converter = TypeDescriptor.GetConverter(@this);
                if (converter != null)
                {
                    if (converter.CanConvertTo(targetType))
                    {
                        return converter.ConvertTo(@this, targetType);
                    }
                }

                converter = TypeDescriptor.GetConverter(targetType);
                if (converter != null)
                {
                    if (converter.CanConvertFrom(@this.GetType()))
                    {
                        return converter.ConvertFrom(@this);
                    }
                }

                if (@this == DBNull.Value)
                {
                    return null;
                }
            }

            return @this;
        }


        /// <summary>
        /// <para>将源对象的属性值映射到target对象上,(target==null时直接返回)</para>
        /// <para>该方法使用反射</para>
        /// <para>源对象和目标对象可以是不同对象,只要属性名称一致即可,如Model1映射到Model2</para>
        /// </summary>
        /// <typeparam name="T">target泛型类</typeparam>
        /// <param name="obj">源对象</param>
        /// <param name="target">目标对象</param>
        public static void MapTo<T>(this object obj, T target) where T : class, new()
        {
            if (obj == null || target == null) return;
            var objProps = obj.GetType().GetProperties();
            if (objProps == null || objProps.Length == 0) return;
            var listObjProps = objProps.ToList();
            //var str = JsonConvert.SerializeObject(obj);
            //var foo = JsonConvert.DeserializeObject<T>(str);
            var props = typeof(T).GetProperties();
            foreach (var item in props)
            {
                if (!item.CanWrite) continue;
                var find = listObjProps.Find(p => p.Name == item.Name);
                if (find == null) continue;


                var value = find.GetValue(obj);
                if (value == null) continue;
                if (item.PropertyType != value.GetType() && !item.PropertyType.Name.Contains("Nullable"))
                {
                    value = Convert.ChangeType(value, item.PropertyType);
                }
                item.SetValue(target, value);
            }
        }

    }
}
