using Newtonsoft.Json;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using static Lucene.Net.Util.Fst.Util;

namespace Hotline.Share.Tools;
public static class ObjectExtensions
{

    /// <summary>
    /// obj 转换成 dictionary
    /// </summary>
    /// <param name="source"> The source.  </param>
    /// <returns> The <see cref="IDictionary"/>.  </returns>
    public static IDictionary<string, object> ToDictionary(this object source)
    {
        return source.ToDictionary<object>();
    }

    /// <summary>
    /// obj 转换成 IDictionary
    /// </summary>
    /// <param name="source"> The source.  </param>
    /// <typeparam name="T"> 返回类型 </typeparam>
    /// <returns> The <see cref="IDictionary"/>.  </returns>
    public static IDictionary<string, T> ToDictionary<T>(this object source)
    {
        if (source == null)
        {
            throw new ArgumentNullException("source", "Unable to convert object to a dictionary. The source object is null.");
        }

        var dictionary = new Dictionary<string, T>();
        if (source is Dictionary<string, object>)
        {
            foreach (var property in (Dictionary<string, object>)source)
            {
                dictionary.Add(property.Key, (T)property.Value);
            }
        }
        else
        {
            foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(source))
            {
                AddPropertyToDictionary<T>(property, source, dictionary);
            }
        }

        return dictionary;
    }

    private static void AddPropertyToDictionary<T>(PropertyDescriptor property, object source, Dictionary<string, T> dictionary)
    {
        object value = property.GetValue(source);
        if (IsOfType<T>(value))
            dictionary.Add(property.Name, (T)value);
    }

    private static bool IsOfType<T>(object value)
    {
        return value is T;
    }

    /// <summary>
    /// 遍历类属性
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="model"></param>
    /// <param name="func">返回 true: contions; false: break</param>
    public static void ForeachClassProperties<T>(this T model, Func<T, PropertyInfo, string, object, Task<bool>> func)
    {
        var t = model.GetType();
        var propertyList = t.GetProperties();
        foreach (var item in propertyList)
        {
            var name = item.Name;
            var value = item.GetValue(model, null);
            var result = func(model, item, name, value).GetAwaiter().GetResult();
            if (result == false) break;
        }
    }

    public static string ToJson(this object obj, JsonSerializerSettings options)
    {
        return obj == null ? default(string) : JsonConvert.SerializeObject(obj, options);
    }

    public static string ToJson(this object obj)
    {
        return obj == null ? default(string) : JsonConvert.SerializeObject(obj);
    }


    public static T FromJson<T>(this string json)
    {
        return json.IsNullOrEmpty() ? default(T) : JsonConvert.DeserializeObject<T>(json);
    }

    public static object? FromJson(this string json, Type returnType)
    {
        return json.IsNullOrEmpty() ? null : JsonConvert.DeserializeObject(json, returnType);
    }
}
