package com.thinkunion.park.service.common.iot.capability.devicemodel;

import com.google.gson.*;
import com.thinkunion.park.service.common.iot.capability.devicemodel.rules.ArrayRule;
import com.thinkunion.park.service.common.iot.capability.devicemodel.rules.EnumRule;
import com.thinkunion.park.service.common.iot.capability.devicemodel.rules.MetaRule;
import com.thinkunion.park.service.common.iot.util.TextUtils;

import java.lang.reflect.Type;
import java.util.List;

public class DataTypeBak<T> {

    private String type;
    private T rules;

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

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

    public T getRules() {
        return this.rules;
    }

    public void setRules(T rules) {
        this.rules = rules;
    }

    public static class DataTypeJsonDeSerializer
            implements JsonDeserializer<DataTypeBak> {

        @Override
        public DataTypeBak deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
                throws JsonParseException {
            if (json == null) {
                return null;
            }
            DataTypeBak<Object> dataType = null;
            if (!json.isJsonObject()) {
                return dataType;
            }
            JsonObject jsonObject = json.getAsJsonObject();
            JsonElement typeElement = jsonObject.get("type");
            JsonElement specsElement = jsonObject.get("rules");
            if (typeElement == null) {
                return dataType;
            }
            String type = typeElement.getAsString();
            if (TextUtils.isEmpty(type)) {
                return dataType;
            }
            dataType = new DataTypeBak<>();
            dataType.setType(type);
            if ("string".equalsIgnoreCase(type) || "bool".equalsIgnoreCase(type) || "int"
                    .equalsIgnoreCase(type) || "float"
                    .equalsIgnoreCase(type) || "double"
                    .equalsIgnoreCase(type) || "text".equalsIgnoreCase(type) || "date".equalsIgnoreCase(type)) {
                MetaRule metaRule = context.deserialize(specsElement, (MetaRule.class));
                dataType.setRules(metaRule);
                return dataType;
            }
            if ("array".equalsIgnoreCase(type)) {
                ArrayRule arrayRule = context.deserialize(specsElement, (ArrayRule.class));
                dataType.setRules(arrayRule);
                return dataType;
            }
            if ("enum".equalsIgnoreCase(type)) {
                EnumRule enumRule = context.deserialize(specsElement, (EnumRule.class));
                dataType.setRules(enumRule);
                return dataType;
            }
            if (!"struct".equalsIgnoreCase(type)) {
                return dataType;
            }
            List structSpec = context.deserialize(specsElement, (List.class));
            dataType.setRules(structSpec);
            return dataType;
        }
    }

    public static class DataTypeJsonSerializer
            implements JsonSerializer<DataTypeBak> {

        @Override
        public JsonElement serialize(DataTypeBak src, Type typeOfSrc, JsonSerializationContext context) {
            JsonElement jsonElement = null;
            if (src == null) {
                return jsonElement;
            }
            JsonObject jsonObject = new JsonObject();
            if ("string".equalsIgnoreCase(src.getType()) || "bool".equalsIgnoreCase(src.getType()) || "int"
                    .equalsIgnoreCase(src.getType()) || "float".equalsIgnoreCase(src.getType()) || "double"
                    .equalsIgnoreCase(src.getType()) || "text".equalsIgnoreCase(src.getType()) || "date"
                    .equalsIgnoreCase(src.getType())) {
                jsonElement = context.serialize(src.getRules(), (MetaRule.class));
            } else if ("array".equalsIgnoreCase(src.getType())) {
                jsonElement = context.serialize(src.getRules(), (ArrayRule.class));
            } else if ("enum".equalsIgnoreCase(src.getType())) {
                jsonElement = context.serialize(src.getRules(), (EnumRule.class));
            } else if ("struct".equalsIgnoreCase(src.getType())) {
                jsonElement = context.serialize(src.getRules(), (List.class));
            }
            jsonObject.addProperty("type", src.getType());
            jsonObject.add("rules", jsonElement);
            return jsonObject;
        }
    }

}

