using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Xml;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace DataMatch.AddressVerification.Helpers
{
    internal class JsonHelper
    {
        public static string Serialize<T>(T obj)
        {
            using (MemoryStream memoryStream = new MemoryStream())
            {
                new DataContractJsonSerializer(obj.GetType()).WriteObject((Stream)memoryStream, (object)obj);
                return Encoding.UTF8.GetString(memoryStream.ToArray());
            }
        }

        /// <summary>
        /// Deserialize json to object tree.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="json"></param>
        /// <returns></returns>
        public static T Deserialize<T>(string json) where T : new()
        {
            if (string.IsNullOrEmpty(json))
            {
                return Activator.CreateInstance<T>();
            }

            json = JsonHelper.EscapeStringValue(json);

            using (MemoryStream memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(json)))
            {
                DataContractJsonSerializer contractJsonSerializer = new DataContractJsonSerializer(typeof(T));

                try
                {
                    return (T)contractJsonSerializer.ReadObject((Stream)memoryStream);
                }
                catch (SerializationException ex)
                {
                    return Activator.CreateInstance<T>();
                }
                catch (XmlException ex)
                {
                    return Activator.CreateInstance<T>();
                }
            }
        }

        public static T ConvertJson<T>(string json) where T : new()
        {
            return JsonConvert.DeserializeObject<T>(json);
        }

        public static object Parse(string json)
        {
            return (object)JObject.Parse(json);
        }

        public static string EscapeStringValue(string value)
        {
            return value.Replace("\r", "\\r").Replace("\n", "\\n").Replace("\t", "\\t");
        }

        public static T Clone<T>(T item)
        {
            return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject((object)item));
        }
    }
}
