using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;

namespace RiskAssessment
{
    public static class JsonExtensions
    {
        private static JsonSerializerSettings DefaultSerializerSettings
        {
            get
            {
                //It's unclear if these classes are thread safe, so we're creating new
                // objects each time.
                return new JsonSerializerSettings {
                    //converting properties to camelCase to follow JS guidelines.
                    ContractResolver = new CamelCasePropertyNamesContractResolver()
                };
            }
        }
        /// <summary>
        /// Serializes the object in JSON format.
        /// </summary>
        /// <param name="value">The object to serialize</param>
        /// <returns>A JSON string representing the object.</returns>
        /// <remarks>Note that the object properties are renamed to camelCase to look better in JavaScript</remarks>
        public static string ToJson(this object value)
        {
            return ToJson(value, DefaultSerializerSettings);
        }

        private static string ToJson(object value, JsonSerializerSettings serializerSettings)
        {
            //maybe one day we can make this private overload another public extension method.
            // But let's wait until that's really needed.

            return JsonConvert.SerializeObject(value, Formatting.Indented, serializerSettings);
        }

        /// <summary>
        /// Deserializes the given JSON data into a new object of type <typeparamref name="T"/>.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="json">The data representing the object to deserialize</param>
        /// <returns>An object of type <typeparamref name="T"/> populated with the JSON data.</returns>
        public static T DeserializeJson<T>(this string json)
        {
            return DeserializeJson<T>(json, DefaultSerializerSettings);
        }

        private static T DeserializeJson<T>(string json, JsonSerializerSettings serializerSettings)
        {
            //maybe one day we can make this private overload another public extension method.
            // But let's wait until that's really needed.

            return JsonConvert.DeserializeObject<T>(json, serializerSettings);
        }

        /// <summary>
        /// Deserializes the given JSON data into a new object of the same type of the given template.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="json">The data representing the object to deserialize</param>
        /// <param name="templateObject">Object that will serve as a template. Think anonymous types.</param>
        /// <returns>An object of type <typeparamref name="T"/> populated with the JSON data.</returns>
        public static T DeserializeJson<T>(this string json, T templateObject)
        {
            return JsonConvert.DeserializeAnonymousType(json, templateObject);
        }

    }

}
