package com.dashitech.utils;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.SerializationFeature;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import net.sf.json.JsonConfig;
import net.sf.json.processors.JsonValueProcessor;
import net.sf.json.util.CycleDetectionStrategy;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;


public class JsonUtil {

    public static JSONObject toJSONObject(Object obj) {
        return JSONObject.fromObject(obj, getJsonConfig());
    }

    public static String toJsonString(Object obj) {
        com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper();
        mapper.setDateFormat(DateUtil.SDF_DATETIME);
        mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
        try {
            return mapper.writeValueAsString(obj);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    public static JSONArray toJSONArray(Object obj) {
        return JSONArray.fromObject(obj, getJsonConfig());
    }

    public static <T> List<T> toList(Object obj, Class<T> clazz) {
        JSONArray arr = toJSONArray(obj);
        @SuppressWarnings({"unchecked", "deprecation"}) List<T> list = JSONArray.toList(arr, clazz);
        return list;
    }

    public static <T> List<T> toList(Object obj, Class<T> clazz, Map classMap) {
        JSONArray arr = toJSONArray(obj);
        @SuppressWarnings({"unchecked", "deprecation"}) List<T> list = JSONArray.toList(arr, clazz, classMap);
        return list;
    }

    /**
     * 会格式化日期为yyyy-MM-dd HH:mm:ss
     */
    @SuppressWarnings({"deprecation"})
    public static <T> List<T> toList2(String json, Class<T> clazz) {
        try {
            com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper();
            mapper.setDateFormat(DateUtil.SDF_DATETIME);
            mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
            mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

            JavaType javaType = mapper.getTypeFactory().constructParametricType(ArrayList.class, clazz);
            List<T> result = mapper.readValue(json, javaType);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 2016-03-01 00:00:00 替换为 2016-03-01 <br/>
     * 如果报错返回原始数据
     */
    public static JSONObject replaceDateTime(JSONObject source) {
        JSONObject result = source;
        try {
            String ss = source.toString();
            String formatJson = ss.replaceAll(" \\d{2}:\\d{2}:\\d{2}", "");
            result = JSONObject.fromObject(formatJson);
        } catch (Exception e) {
        }
        return result;
    }


    public static <T> T toObject(String json, Class<T> valueType) {
        com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper();
        mapper.setDateFormat(DateUtil.SDF_DATETIME);
        mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);

        try {
            return mapper.readValue(json, valueType);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static <T> List<T> toListObject(String json, Class<T> valueType) {
        com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper();
        mapper.setDateFormat(DateUtil.SDF_DATETIME);
        mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);

        try {
            List<T> result = new ArrayList<>();
            List<Map> list = mapper.readValue(json, ArrayList.class);
            for (Map map : list) {
                T t = toObject(toJSONObject(map).toString(), valueType);
                result.add(t);
            }
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static JsonConfig getJsonConfig() {
        JsonConfig config = new JsonConfig();
        //去掉class
        config.setIgnoreDefaultExcludes(false);
        //禁止自包含
        config.setCycleDetectionStrategy(CycleDetectionStrategy.LENIENT);
        //处理日期转换
        config.registerJsonValueProcessor(Date.class, new Date_JsonValueProcessor());
        return config;
    }

}

class Date_JsonValueProcessor implements JsonValueProcessor {

    public Object processArrayValue(Object value, JsonConfig config) {
        return process(value, config);
    }

    public Object processObjectValue(String key, Object value, JsonConfig config) {
        return process(value, config);
    }

    ;

    private Object process(Object value, JsonConfig config) {
        if (value == null) {
            return "";
        }
        if (value instanceof Date) {
            String date = DateUtil.SDF_DATETIME.format((Date) value);
            return date;
        } else {
            return value == null ? null : value.toString();
        }
    }

}