package com.thinkunion.park.service.common.iot.capability.device.payload;

import com.google.gson.*;
import com.google.gson.reflect.TypeToken;

import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.*;
import java.util.Map.Entry;

public class ValueWrapper<T> {

    private static final String TAG = "[Tmp]ValueWrapper";
    protected String type;
    protected T value;
    private static Method isIntegralMethod = null;

    public ValueWrapper(T valuePar) {
        this.value = valuePar;
    }

    public ValueWrapper() {
    }

    public T getValue() {
        return this.value;
    }

    public void setValue(T value) {
        this.value = value;
    }

    public String getType() {
        return this.type;
    }

    public void setType(String t) {
        this.type = t;
    }

    public static boolean isIntegral(JsonPrimitive primitive) {
        try {
            if (isIntegralMethod == null) {
                Class<?> threadClazz = Class.forName("com.google.gson.JsonPrimitive");
                isIntegralMethod = threadClazz.getDeclaredMethod("isIntegral", JsonPrimitive.class);
                isIntegralMethod.setAccessible(true);
            }

            return (Boolean) isIntegralMethod.invoke(JsonPrimitive.class, primitive);
        } catch (Exception var2) {
            var2.printStackTrace();
            return false;
        }
    }

    public static boolean isInteger(JsonPrimitive primitive) {
        String numberStr = primitive.getAsString();
        return !numberStr.contains(".") && !numberStr.contains("e") && !numberStr.contains("E");
    }

    public static class ValueWrapperJsonDeSerializer implements JsonDeserializer<ValueWrapper> {

        public ValueWrapperJsonDeSerializer() {
        }

        public ValueWrapper deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
                throws JsonParseException {
            if (json == null) {
                return null;
            } else {
                ValueWrapper valueWrapper = null;
                if (json.isJsonObject()) {
                    StructValueWrapper structValueWrapper = new StructValueWrapper();
                    JsonObject jsonObject = json.getAsJsonObject();
                    Set<String> keySets = jsonObject.keySet();
                    Iterator iterator = keySets.iterator();

                    while (iterator.hasNext()) {
                        String key = (String) iterator.next();
                        structValueWrapper
                                .addValue(key, context.deserialize(jsonObject.get(key), ValueWrapper.class));
                    }

                    valueWrapper = structValueWrapper;
                } else if (json.isJsonArray()) {
                    ArrayValueWrapper arrayValueWrapper = new ArrayValueWrapper();
                    JsonArray jsonArray = json.getAsJsonArray();

                    for (int i = 0; i < jsonArray.size(); ++i) {
                        JsonElement jsonArrayElement = jsonArray.get(i);
                        arrayValueWrapper.add(context.deserialize(jsonArrayElement, ValueWrapper.class));
                    }

                    valueWrapper = arrayValueWrapper;
                } else if (json.isJsonPrimitive()) {
                    JsonPrimitive jsonPrimitive = json.getAsJsonPrimitive();
                    if (jsonPrimitive == null) {
                        return null;
                    }

                    if (jsonPrimitive.isBoolean()) {
                        valueWrapper = new BooleanValueWrapper(jsonPrimitive.getAsInt());
                    } else if (jsonPrimitive.isString()) {
                        valueWrapper = new StringValueWrapper(jsonPrimitive.getAsString());
                    } else if (jsonPrimitive.isNumber()) {
                        if (ValueWrapper.isInteger(jsonPrimitive)) {
                            valueWrapper = new IntValueWrapper(jsonPrimitive.getAsInt());
                        } else {
                            valueWrapper = new DoubleValueWrapper(jsonPrimitive.getAsDouble());
                        }
                    } else if (jsonPrimitive.isJsonObject()) {
                        StructValueWrapper structValueWrapper = new StructValueWrapper();
                        JsonObject jsonObject = jsonPrimitive.getAsJsonObject();
                        Set<String> keySets = jsonObject.keySet();
                        Iterator iterator = keySets.iterator();

                        while (iterator.hasNext()) {
                            String key = (String) iterator.next();
                            structValueWrapper
                                    .addValue(key, context.deserialize(jsonObject.get(key), ValueWrapper.class));
                        }

                        valueWrapper = structValueWrapper;
                    }
                }

                return valueWrapper;
            }
        }
    }

    public static class ValueWrapperJsonSerializer implements JsonSerializer<ValueWrapper> {

        public ValueWrapperJsonSerializer() {
        }

        public JsonElement serialize(ValueWrapper src, Type typeOfSrc, JsonSerializationContext context) {
            JsonElement jsonElement = null;
            if (src == null) {
                return jsonElement;
            } else {
                if (src != null) {
                    if (!"int".equalsIgnoreCase(src.getType()) && !"enum".equalsIgnoreCase(src.getType())) {
                        if (!"string".equalsIgnoreCase(src.getType()) && !"date".equalsIgnoreCase(src.getType())) {
                            if ("bool".equalsIgnoreCase(src.getType())) {
                                jsonElement = new JsonPrimitive((Integer) src.getValue());
                            } else if (!"double".equalsIgnoreCase(src.getType()) && !"float"
                                    .equalsIgnoreCase(src.getType())) {
                                Iterator iterator;
                                if ("array".equalsIgnoreCase(src.getType())) {
                                    List<ValueWrapper> objectList = (List) src.getValue();
                                    JsonArray jsonArray = new JsonArray();
                                    if (objectList != null && !objectList.isEmpty()) {
                                        iterator = objectList.iterator();

                                        while (iterator.hasNext()) {
                                            ValueWrapper obj = (ValueWrapper) iterator.next();
                                            jsonArray.add(context.serialize(obj, (new TypeToken<ValueWrapper>() {
                                            }).getType()));
                                        }
                                    } else {
                                        // TODO
                                    }

                                    jsonElement = jsonArray;
                                } else if ("struct".equalsIgnoreCase(src.getType())) {
                                    JsonObject jsonObject = new JsonObject();
                                    StructValueWrapper structValueWrapper = (StructValueWrapper) src;
                                    if (src.getValue() != null) {
                                        iterator = structValueWrapper.getValue().entrySet().iterator();

                                        while (iterator.hasNext()) {
                                            Entry<String, ValueWrapper> entry = (Entry) iterator.next();
                                            jsonObject.add(entry.getKey(),
                                                    context.serialize(entry.getValue(), (new TypeToken<ValueWrapper>() {
                                                    }).getType()));
                                        }
                                    }

                                    jsonElement = jsonObject;
                                } else {
                                    jsonElement = context.serialize(src.getValue());
                                }
                            } else {
                                jsonElement = new JsonPrimitive((Double) src.getValue());
                            }
                        } else {
                            jsonElement = new JsonPrimitive((String) src.getValue());
                        }
                    } else {
                        jsonElement = new JsonPrimitive((Integer) src.getValue());
                    }
                }

                return jsonElement;
            }
        }
    }

    public static class StructValueWrapper extends ValueWrapper<Map<String, ValueWrapper>> {

        public StructValueWrapper() {
            this(new HashMap());
        }

        public StructValueWrapper(Map<String, ValueWrapper> valueParam) {
            this.type = "struct";
            this.value = valueParam;
        }

        public ValueWrapper addValue(String key, ValueWrapper valueWrapper) {
            if (this.value == null) {
                this.value = new HashMap();
            }

            return (ValueWrapper) ((Map) this.value).put(key, valueWrapper);
        }

        public Map<String, ValueWrapper> getValue() {
            return (Map) this.value;
        }

        public void setValue(Map<String, ValueWrapper> valueList) {
            this.value = valueList;
        }
    }

    public static class ArrayValueWrapper extends ValueWrapper<List<ValueWrapper>> {

        public ArrayValueWrapper() {
            this.type = "array";
        }

        public ArrayValueWrapper(List<ValueWrapper> valueParam) {
            this();
            this.value = valueParam;
        }

        public List<ValueWrapper> getValue() {
            return this.value;
        }

        public void add(ValueWrapper obj) {
            if (this.value == null) {
                this.value = new ArrayList();
            }

            (this.value).add(obj);
        }

        public void setValue(List<ValueWrapper> valueParam) {
            this.value = valueParam;
        }
    }

    public static class DoubleValueWrapper extends ValueWrapper<Double> {

        public DoubleValueWrapper() {
            this.type = "double";
        }

        public DoubleValueWrapper(Double valueParam) {
            this();
            this.value = valueParam;
        }

        public Double getValue() {
            return (Double) this.value;
        }

        public void setValue(Double valueParam) {
            this.value = valueParam;
        }
    }

    public static class BooleanValueWrapper extends IntValueWrapper {

        public BooleanValueWrapper() {
            this.type = "bool";
        }

        public BooleanValueWrapper(Integer valueParam) {
            this();
            this.value = valueParam;
        }
    }

    public static class StringValueWrapper extends ValueWrapper<String> {

        public StringValueWrapper() {
            this.type = "string";
        }

        public StringValueWrapper(String valuePar) {
            this();
            this.value = valuePar;
        }

        public String getValue() {
            return (String) this.value;
        }

        public void setValue(String value) {
            this.value = value;
        }
    }

    public static class EnumValueWrapper extends IntValueWrapper {

        public EnumValueWrapper() {
            this.type = "enum";
        }

        public EnumValueWrapper(int valuePar) {
            this();
            this.setValue(valuePar);
        }
    }

    public static class DateValueWrapper extends StringValueWrapper {

        public DateValueWrapper() {
            this.type = "date";
        }

        public DateValueWrapper(String valuePar) {
            this();
            this.setValue(valuePar);
        }
    }

    public static class IntValueWrapper extends ValueWrapper<Integer> {

        public IntValueWrapper() {
            this.type = "int";
        }

        public IntValueWrapper(int valueParam) {
            this();
            this.value = valueParam;
        }

        public Integer getValue() {
            return this.value;
        }

        public void setValue(int value) {
            this.value = value;
        }
    }
}
