using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.IO;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Converters;

namespace Mammonth.Common
{
    
    /// <summary>
    /// JSON处理类
    /// </summary>
    /// <remarks>
    /// 维护：zhao 
    /// 最后编辑：zhao 2013-11-13 增加获取最后异常信息
    /// </remarks>
    public class JSON {

        public static string DateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss";

        /// <summary>
        /// 最后错误
        /// </summary>
        private static string strLastError;
        /// <summary>
        /// 获取最后错误
        /// </summary>
        /// <returns></returns>
        public static string GetLastError() {
            return strLastError;
        }
        //private string MySerializeObject(Object value)
        //{
        //    StringWriter sw = new StringWriter();
        //    JsonSerializer jsonSerializer = new JsonSerializer();
        //    jsonSerializer.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
        //    using (JsonWriter jsonWriter = new JsonWriter(sw))
        //    {
        //        jsonWriter.Formatting = Formatting.Indented;
        //        jsonSerializer.Serialize(jsonWriter, value);
        //    }
        //    return sw.ToString();
        //}
        //JsonConvert.SerializeObject(YourPOCOHere, Formatting.Indented, 
        //new JsonSerializerSettings() { 
        //        ReferenceLoopHandling = ReferenceLoopHandling.Serialize
        //});
        /// <summary>
        /// 格式化成字符串
        /// 修改人:yangguoji
        /// 修改时间:2014-04-29 15:24:44
        /// 修改内容:使用JsonSerializerSettings设置为忽略循环引用
        /// </summary>
        /// <param name="o"></param>
        /// <returns></returns>
        public static string Encode(object o) {
            if (o == null || o.ToString() == "null") return null;

            if (o != null && (o.GetType() == typeof(String) || o.GetType() == typeof(string))) {
                return o.ToString();
            }

            //config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore; 
            IsoDateTimeConverter dt = new IsoDateTimeConverter();
            dt.DateTimeFormat = DateTimeFormat;

            JsonSerializerSettings jsSet = new JsonSerializerSettings() {
                ReferenceLoopHandling = ReferenceLoopHandling.Ignore
            };
            jsSet.Converters.Add(dt);

            //JSON序列化  
            return JsonConvert.SerializeObject(o, jsSet);//


            // return JsonConvert.SerializeObject(o, Formatting.None, jsSet);            
        }

        //private string MySerializeObject(Object value)
        //{
        //    StringWriter sw = new StringWriter(CultureInfo.InvariantCulture);
        //    JsonSerializer jsonSerializer = new JsonSerializer();
        //    jsonSerializer.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
        //    using (JsonWriter jsonWriter = new JsonWriter(sw))
        //    {
        //        jsonWriter.Formatting = Formatting.Indented;
        //        jsonSerializer.Serialize(jsonWriter, value);
        //    }
        //    return sw.ToString();
        //}
        public static string Encode(object o, out string msg) {
            msg = "";
            try {
                if (o == null || o.ToString() == "null") return "";

                if (o != null && (o.GetType() == typeof(String) || o.GetType() == typeof(string))) {
                    return o.ToString();
                }
                IsoDateTimeConverter dt = new IsoDateTimeConverter();
                dt.DateTimeFormat = DateTimeFormat;
                return JsonConvert.SerializeObject(o, dt);
            } catch (System.Exception ex) {
                msg = ex.Message;
                return "";
            }
        }

        /// <summary>
        /// 格式化
        /// </summary>
        /// <param name="json"></param>
        /// <returns></returns>
        public static object Decode(string json) {
            if (String.IsNullOrEmpty(json))
                return "";
            object o = JsonConvert.DeserializeObject(json);
            if (o.GetType() == typeof(String) || o.GetType() == typeof(string)) {
                o = JsonConvert.DeserializeObject(o.ToString());
            }
            object v = toObject(o);
            return v;
        }

        ///// <summary>
        ///// 格式化
        ///// </summary>
        ///// <param name="json"></param>
        ///// <param name="type"></param>
        ///// <returns></returns>
        //public static object Decode(string json, Type type)
        //{
        //    json = json.Replace(":\"Y\"", "1");
        //    json = json.Replace(":\"N\"", "0");
        //    return JsonConvert.DeserializeObject(json, type);
        //}


        /// <summary>
        /// 格式化为指定的类型
        /// 创建：赵 2012-12-6 
        /// </summary>
        /// <typeparam name="T">指定的类型,完全限定名称</typeparam>
        /// <param name="json">json字符串</param>
        /// <returns></returns>
        public static T Decode<T>(string json) {
            //json = json.Replace(":\"Y\"", ":\"true\"");
            //json = json.Replace(":\"N\"", ":\"false\"");
            try {
                return (T)JsonConvert.DeserializeObject(json, typeof(T));
            } catch (Newtonsoft.Json.JsonSerializationException ex) {
                Exception bex = ex.GetBaseException();
                strLastError = (bex != null && !bex.Equals(ex)) ? bex.Message + ex.Message : ex.Message;
                return default(T);
            } catch (System.Exception ex) {
                strLastError = ex.Message;
                return default(T);
            }

        }


        /// <summary>
        /// 格式化为指定的类型
        /// 创建：赵 2012-12-6 
        /// </summary>
        /// <typeparam name="T">指定的类型,完全限定名称</typeparam>
        /// <param name="json">json字符串</param>
        /// <returns></returns>
        public static T Decode<T>(Hashtable row) {
            string json = Encode(row);
            return (T)JsonConvert.DeserializeObject(json, typeof(T));
        }


        private static object toObject(object o) {
            if (o == null) return null;

            if (o.GetType() == typeof(string)) {
                //判断是否符合2010-09-02T10:00:00的格式
                string s = o.ToString();
                if (s.Length == 19 && s[10] == 'T' && s[4] == '-' && s[13] == ':') {
                    o = System.Convert.ToDateTime(o);
                }
            } else if (o is JObject) {
                JObject jo = o as JObject;

                Hashtable h = new Hashtable();

                foreach (KeyValuePair<string, JToken> entry in jo) {
                    h[entry.Key] = toObject(entry.Value);
                }

                o = h;
            } else if (o is IList) {

                ArrayList list = new ArrayList();
                list.AddRange((o as IList));
                int i = 0, l = list.Count;
                for (; i < l; i++) {
                    list[i] = toObject(list[i]);
                }
                o = list;

            } else if (typeof(JValue) == o.GetType()) {
                JValue v = (JValue)o;
                o = toObject(v.Value);
            } else {
            }
            return o;
        }


        #region 添加人:yangguoji 添加时间：2013-08-24 15:18:48

        /// <summary>
        /// 把对象序列化成json字符串，并指定时间类型属性的转换格式
        /// 作者:yangguoji
        /// 时间:2014-03-11 15:53:29
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="t">要序列化的对象</param>
        /// <param name="dateFormatString">时间格式</param>
        /// <returns></returns>
        public static string SerializeObject<T>(T t, string dateFormatString = "yyyy-MM-dd HH:mm:ss") {
            IsoDateTimeConverter dt = new IsoDateTimeConverter();
            dt.DateTimeFormat = dateFormatString;
            return JsonConvert.SerializeObject(t, dt);
        }
        /// <summary>
        /// 将json字符串反序列化成匿名对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="value"></param>
        /// <param name="t"></param>
        /// <returns></returns>
        public static T DecodeAnonymousType<T>(string value, T t) {
            return JsonConvert.DeserializeAnonymousType(value, t);
        }
        #endregion
    }
}
