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

namespace Vinno.vCloud.Disk
{
    /// <summary>
    /// use to convert data type
    /// </summary>
    public static class ConvertHelper
    {
        /// <summary>
        /// convert object to Json string
        /// </summary>
        /// <param name="obj">object</param>
        /// <param name="formatting">format</param>
        /// <param name="settings">settings</param>
        /// <returns></returns>
        public static string ToJson(this object obj, Formatting formatting = Formatting.None, JsonSerializerSettings settings = null)
        {
            if (obj == null) return string.Empty;
            try
            {
                return JsonConvert.SerializeObject(obj, formatting, settings);
            }
            catch { return string.Empty; }
        }

        /// <summary>
        /// convert Json string to object
        /// </summary>
        /// <typeparam name="T">object type</typeparam>
        /// <param name="jsonStr">Json string</param>
        /// <param name="settings">settings</param>
        /// <returns></returns>
        public static T JsonToObj<T>(this string jsonStr, JsonSerializerSettings settings = null)
        {
            if (string.IsNullOrWhiteSpace(jsonStr)) return default(T);
            try
            {
                return JsonConvert.DeserializeObject<T>(jsonStr, settings);
            }
            catch { return default(T); }
        }

        /// <summary>
        /// convert Json string to object
        /// </summary>
        /// <param name="jsonStr">Json string</param>
        /// <param name="type">object type</param>
        /// <param name="settings">settings</param>
        /// <returns></returns>
        public static object JsonToObj(this string jsonStr, Type type, JsonSerializerSettings settings = null)
        {
            if (string.IsNullOrWhiteSpace(jsonStr)) return type.IsValueType ? Activator.CreateInstance(type) : null;
            try
            {
                return JsonConvert.DeserializeObject(jsonStr, type, settings);
            }
            catch { return type.IsValueType ? Activator.CreateInstance(type) : null; }
        }
        /// <summary>
        /// convert sting to int
        /// </summary>
        /// <param name="str">string</param>
        /// <param name="defaultValue">default Value</param>
        /// <returns></returns>
        public static int ToInt(this string str, int defaultValue = 0)
        {
            if (string.IsNullOrWhiteSpace(str)) return defaultValue;
            int.TryParse(str, out defaultValue);
            return defaultValue;
        }

        public static double ToDouble(this string str, double defaultValue = 0)
        {
            if (string.IsNullOrWhiteSpace(str)) return defaultValue;
            double.TryParse(str, out defaultValue);
            return defaultValue;
        }

        /// <summary>
        /// convert sting to float
        /// </summary>
        /// <param name="str"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static float ToFloat(this string str, float defaultValue = 0)
        {
            if (string.IsNullOrWhiteSpace(str)) return defaultValue;
            float.TryParse(str, out defaultValue);
            return defaultValue;
        }

        /// <summary>
        /// convert sting to DateTime
        /// </summary>
        /// <param name="str"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static DateTime ToDateTime(this string str)
        {
            DateTime defaultValue;
            if (string.IsNullOrWhiteSpace(str)) return DateTime.MinValue;
            DateTime.TryParse(str, out defaultValue);
            return defaultValue;
        }

        /// <summary>
        /// convert sting to int
        /// </summary>
        /// <param name="str">string</param>
        /// <param name="defaultValue">default Value</param>
        /// <returns></returns>
        public static long ToLong(this string str, long defaultValue = 0)
        {
            if (string.IsNullOrWhiteSpace(str)) return defaultValue;
            long.TryParse(str, out defaultValue);
            return defaultValue;
        }

        /// <summary>
        /// Convert string to other type object
        /// </summary>
        /// <param name="str">string</param>
        /// <param name="type">type</param>
        /// <returns></returns>
        public static object ToObject(this string str, Type type)
        {
            try
            {
                return Convert.ChangeType(str, type, CultureInfo.InvariantCulture);
            }
            catch
            {
                return type.IsValueType ? Activator.CreateInstance(type) : null;
            }
        }

        /// <summary>
        /// convert sting to Boolean
        /// </summary>
        /// <param name="str">sting</param>
        /// <returns></returns>
        public static bool ToBool(this string str)
        {
            if (string.IsNullOrWhiteSpace(str)) return false;
            bool.TryParse(str, out bool val);
            return val;
        }

        public static bool IsEmpty(this string str)
        {
            if (string.IsNullOrWhiteSpace(str))
            {
                return true;
            }
            return false;
        }
    }

    /// <summary>
    /// Limit Props Contract Resolver
    /// </summary>
    public class LimitPropsContractResolver : DefaultContractResolver
    {
        string[] props = null;

        bool retain;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="props"></param>
        /// <param name="retain"></param>
        public LimitPropsContractResolver(string[] props, bool retain = true)
        {
            this.props = props;
            this.retain = retain;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="type"></param>
        /// <param name="memberSerialization"></param>
        /// <returns></returns>
        protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
        {
            IList<JsonProperty> list =
            base.CreateProperties(type, memberSerialization);
            return list.Where(p =>
            {
                if (retain) return props.Contains(p.PropertyName);
                else return !props.Contains(p.PropertyName);
            }).ToList();
        }
    }
}