package com.sw.mes.utils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.sw.mes.core.utils.DateUtil;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.*;

public class JSONUtils {

    /**
     * 将普通json转换成map
     * @param str
     * @param res
     * @return
     */
    public static boolean iteraJson(String str,Map res){
        //因为json串中不一定有逗号，但是一定有：号，所以这里判断没有则已经value了
        if(str.indexOf(":") == -1){
            return true;
        }
        JSONObject jsonObject = JSONObject.parseObject(str);
        Iterator keys = jsonObject.keySet().iterator();
        while(keys.hasNext()){
            String key = keys.next().toString();
            Object value = jsonObject.get(key);
            if(iteraJson(value.toString(),res)){
                res.put(key, value);
            }
        }
        return false;
    }

    /**
     * 将多层json转换成map，
     * @param source
     * @param map
     * @return
     */
    public static boolean iteraJsonOrArray(String source,Map map){
        if(source.indexOf(":") == -1){
            return true;
        }
        JSONObject fromObject = JSONObject.parseObject(source);
        Iterator keys = fromObject.keySet().iterator();
        while(keys.hasNext()){
            String key = keys.next().toString();
            Object value = fromObject.get(key);
            String val = value.toString();
            if(val.indexOf("[{") == -1){
                //说明不存在数组json即格式为："[{" 开头的数据。可以允许是[10,11,12]的非json数组
                if(val.indexOf(":") == -1){
                    map.put(key, value);
                }else{
                    iteraJson(val, map);
                }
            }else if(val.indexOf("[{") != -1){
                //说明存在数组json即格式为：[{开头的json数组
                if(val.indexOf("[{") == 0){
                    //说明当前value就是一个json数组
                    //去除[括号
                    String jsons = val.substring(1, val.lastIndexOf("]"));//得到数据格式为：{...},{...},{...}
                    //把上面得到jsons分割成数组
                    //因为数据格式为{name:joker,age:20},{...},{...}，所以不能用逗号分割。否则会变"{name:joker" "age:20}"
                    //使用正则表达式把},{替换成}|{
                    jsons = jsons.replaceAll("\\}\\s?,\\s?\\{", "}|{");
                    String[] split = jsons.split("\\|");

                    List<String> list = new ArrayList<>();
                    Map<String, Object> tempMap = null;

                    for(int i = 0; i < split.length;i++){
                        tempMap = new HashMap<>();
                        iteraJsonOrArray(split[i],tempMap);//符合当前递归条件
                    }
                    map.put(key, list);

                }else{
                    //说明value可能是一个json，这个json中任然包含数组。例如：{inner:[{a:1,b:2,c:3}]}
                    iteraJsonOrArray(val,map);//符合当前递归条件
                }
            }

        }
        return false;
    }

    public static Object getJSONObjectValue(JSONObject jsonObject, Class fieldType, String field) {

        if(jsonObject == null || fieldType == null || StringUtils.isBlank(field)) {
            return null;
        }
        Object obj;
        switch (fieldType.getSimpleName()) {
            case "String" :
                obj = jsonObject.getString(field);
                break;
            case "double" :
            case "Double" :
                obj = jsonObject.getDouble(field);
                break;
            case "int" :
            case "Integer" :
                obj = jsonObject.getInteger(field);
                break;
            case "Date" :
                obj = DateUtil.toDate(jsonObject.getString(field));
                break;
            case "long" :
            case "Long" :
                obj = jsonObject.getLong(field);
                break;
            case "boolean" :
            case "Boolean" :
                obj = jsonObject.getBoolean(field);
                break;
            default:
                obj = jsonObject.get(field);
        }
        return obj;
    }


    /**
     * 将普通json转换成map
     * @param str
     * @param fieldMap
     * @param returnMap
     * @return
     */
    public static boolean iteraJson(String str, Map<String, Class> fieldMap, Map<String, Object> returnMap){
        if(str.indexOf(":") == -1){
            return true;
        }

        JSONObject jsonObject = JSONObject.parseObject(str);
        Iterator keys = jsonObject.keySet().iterator();
        while(keys.hasNext()){
            String key = keys.next().toString();
            Object value = jsonObject.get(key);
            if(iteraJson(value.toString(),returnMap)){
                if(fieldMap.containsKey(key)) {
                    returnMap.put(key, getJSONObjectValue(jsonObject, fieldMap.get(key), key));
                }
            }
        }
        return false;
    }

    /**
     * 将多层json转换成map，
     * @param source
     * @param clz
     * @return
     */
    public static <T> T iteraJsonOrArray(String source, Class<T> clz) {

        if(StringUtils.isBlank(source)) {
            return null;
        }

        if(source.indexOf(":") == -1){
            return null;
        }

        //实体中定义的全部属性。
        Field[] fields = clz.getDeclaredFields();
        Map<String, Class> fieldMap = new HashMap<>();

        for (Field field: fields) {
            fieldMap.put(field.getName(), field.getType());
        }

        Map<String, Object> values = new HashMap<>();

        iteratJSONObjectOrArray(source, fieldMap, values);

        //反射动态创建实例。
        Object obj = null;
        try {
            obj = clz.newInstance();
            Iterator iterator = values.keySet().iterator();
            while (iterator.hasNext()) {
                String attName = iterator.next().toString();
                String firChar = String.valueOf(attName.charAt(0));
                String attWord = attName.replaceFirst(firChar, firChar.toUpperCase());
                try {

                    //属性的setter方法
                    if(fieldMap.get(attName).getSimpleName().contains("[]")) {
                        String simpleName = fieldMap.get(attName).getSimpleName();

                        if("Double[]".equalsIgnoreCase(simpleName)) {
                            Method mth = clz.getDeclaredMethod("set" + attWord, Double[].class);
                            JSONArray jsonArray = (JSONArray) values.get(attName);
                            Double[] temp = new Double[jsonArray.size()];
                            for (int i = 0; i < jsonArray.size(); i++ ) {
                                temp[i] = ((BigDecimal) jsonArray.get(i)).doubleValue();
                            }
                            mth.invoke(obj, (Object) temp);
                        }
                        if("String[]".equalsIgnoreCase(simpleName)) {
                            Method mth = clz.getDeclaredMethod("set" + attWord, String[].class);
                            JSONArray jsonArray = (JSONArray) values.get(attName);
                            String[] temp = new String[jsonArray.size()];
                            for (int i = 0; i < jsonArray.size(); i++ ) {
                                temp[i] = (String) jsonArray.get(i);
                            }
                            mth.invoke(obj, (Object) temp);
                        }
                    } else {
                        Method mth = clz.getDeclaredMethod("set" + attWord, fieldMap.get(attName));
                        mth.invoke(obj, values.get(attName));
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    continue;
                }
            }

        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

        return (T) obj;
    }

    public static boolean iteratJSONObjectOrArray(String source, Map<String, Class> fieldMap, Map<String, Object> values){

        if(source.indexOf(":") == -1){
            return true;
        }

        JSONObject fromObject = JSONObject.parseObject(source);
        Iterator keys = fromObject.keySet().iterator();
        while(keys.hasNext()){
            String key = keys.next().toString();
            Object value = fromObject.get(key);
            String val = value.toString();
            if(val.indexOf("[{") == -1){
                if(val.indexOf(":") == -1){
                    if(fieldMap.containsKey(key)) {
                        values.put(key, getJSONObjectValue(fromObject, fieldMap.get(key), key));
                    }
                }else{
                    iteraJson(val, fieldMap, values);
                }
            }else if(val.indexOf("[{") != -1){
                if(val.indexOf("[{") == 0){
                    String jsons = val.substring(1, val.lastIndexOf("]"));//得到数据格式为：{...},{...},{...}
                    jsons = jsons.replaceAll("\\}\\s?,\\s?\\{", "}|{");
                    String[] split = jsons.split("\\|");

                    List<String> list = new ArrayList<>();
                    Map<String, Object> tempMap = null;

                    for(int i = 0; i < split.length;i++){
                        tempMap = new HashMap<>();
                        iteratJSONObjectOrArray(split[i], fieldMap, tempMap);//符合当前递归条件
                    }
                    values.put(key, list);
                }else{
                    iteratJSONObjectOrArray(val,fieldMap, values);//符合当前递归条件
                }
            }
        }
        return false;
    }

}
