using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

/// <summary>
/// JsonExtensions
/// </summary>
public static class JsonExtensions {

    /// <summary>
    /// TryGetValue
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="jobj"></param>
    /// <param name="propertyName"></param>
    /// <param name="valueIfnotexist"></param>
    /// <returns></returns>
    public static T GetValueOrDefault<T>(this JObject jobj, string propertyName, T valueIfnotexist = default(T)) {
        if (jobj.TryGetValue(propertyName, out var value)) {
            return value.ToObject<T>();
        }
        return valueIfnotexist;
    }

    /// <summary>
    /// TryGetValue
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="jobj"></param>
    /// <param name="propertyName"></param>
    /// <param name="tokenType"></param>
    /// <param name="valueIfnotexist"></param>
    /// <returns></returns>
    public static T GetValueOrDefault<T>(this JObject jobj, string propertyName, JTokenType tokenType, T valueIfnotexist = default(T)) {
        if (jobj.TryGetValue(propertyName, out var value) && value.Type == tokenType) {
            return value.ToObject<T>();
        }
        return valueIfnotexist;
    }

    /// <summary>
    /// TryGetValue
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="jobj"></param>
    /// <param name="propertyName"></param>
    /// <param name="tokenType"></param>
    /// <param name="outValue"></param>
    /// <returns></returns>
    public static bool TryGetValue<T>(this JObject jobj, string propertyName, JTokenType tokenType, out T outValue) {
        outValue = default(T);
        if (jobj.TryGetValue(propertyName, out var value) && value.Type == tokenType) {
            outValue = value.ToObject<T>();
            return true;
        }
        return false;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="instance"></param>
    /// <returns></returns>
    public static JToken ToJson(this object instance) => JToken.FromObject(instance);
    
    /// <summary>
    /// 
    /// </summary>
    /// <param name="instance"></param>
    /// <returns></returns>
    public static string ToJsonString(this object instance) => JToken.FromObject(instance).ToString(Formatting.None);

    /// <summary>
    /// parse json string then Deserialze to object
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="str"></param>
    /// <returns></returns>
    public static T ParseJsonToObject<T>(this string str) => JToken.Parse(str).ToObject<T>();

    /// <summary>
    /// 
    /// </summary>
    /// <param name="instance"></param>
    /// <returns></returns>
    public static JObject ToJObject(this object instance) => JObject.FromObject(instance);
    
    /// <summary>
    /// 
    /// </summary>
    /// <param name="instances"></param>
    /// <returns></returns>
    public static JArray ToJArray(this IEnumerable instances) => JArray.FromObject(instances);
}
