package com.kii.thingif.internal.gson;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.kii.thingif.clause.trigger.TriggerClause;
import com.kii.thingif.trigger.Condition;
import com.kii.thingif.trigger.Predicate;
import com.kii.thingif.trigger.ScheduleOncePredicate;
import com.kii.thingif.trigger.SchedulePredicate;
import com.kii.thingif.trigger.StatePredicate;
import com.kii.thingif.trigger.TriggersWhen;

import java.lang.reflect.Type;

public class PredicateAdapter implements
        JsonSerializer<Predicate>,
        JsonDeserializer<Predicate>{
    private Gson gson = new GsonBuilder()
            .registerTypeAdapter(TriggerClause.class, new TriggerClauseAdapter())
            .create();
    @Override
    public JsonElement serialize(Predicate src, Type typeOfSrc, JsonSerializationContext context) {
        if (src == null) return null;

        if (src instanceof StatePredicate) {
            JsonElement clause = gson.toJsonTree(
                    ((StatePredicate) src).getCondition().getClause(),
                    TriggerClause.class);
            JsonObject json = new JsonObject();
            json.add("condition", clause);
            json.addProperty("triggersWhen", ((StatePredicate) src).getTriggersWhen().name());
            json.addProperty("eventSource", src.getEventSource().name());
            return json;
        }else {
            JsonObject ret = gson.toJsonTree(src).getAsJsonObject();
            ret.addProperty("eventSource", src.getEventSource().name());
            return ret;
        }
    }

    @Override
    public Predicate deserialize(JsonElement jsonElement, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        if (jsonElement == null || !jsonElement.isJsonObject()) return null;
        JsonObject json = jsonElement.getAsJsonObject();
        if (!json.has("eventSource")) {
            throw new JsonParseException("not eventSource found");
        }
        String eventSource = json.get("eventSource").getAsString();
        if (eventSource.equals("STATES")) {
            JsonObject clauseJson = json.get("condition").getAsJsonObject();
            String triggerWhenString = json.get("triggersWhen").getAsString();
            TriggersWhen triggersWhen;
            if (triggerWhenString.equals("CONDITION_TRUE")) {
                triggersWhen = TriggersWhen.CONDITION_TRUE;
            }else if (triggerWhenString.equals("CONDITION_FALSE_TO_TRUE")) {
                triggersWhen = TriggersWhen.CONDITION_FALSE_TO_TRUE;
            }else if (triggerWhenString.equals("CONDITION_CHANGED")) {
                triggersWhen = TriggersWhen.CONDITION_CHANGED;
            }else {
                throw new JsonParseException("invalid triggersWhen");
            }
            Condition condition = new Condition(gson.fromJson(clauseJson, TriggerClause.class));
            return new StatePredicate(condition, triggersWhen);
        }else if (eventSource.equals("SCHEDULE")) {
            String schedule = json.get("schedule").getAsString();
            return new SchedulePredicate(schedule);
        }else if (eventSource.equals("SCHEDULE_ONCE")) {
            long scheduleAt = json.get("scheduleAt").getAsLong();
            return new ScheduleOncePredicate(scheduleAt);
        }else {
            throw new JsonParseException("invalid eventSource value");
        }
    }
}

@@ -1402,20 +1402,19 @@
 nObject 
-json
+ret
  = new J
@@ -1434,28 +1434,27 @@
             
-json
+ret
 .add(%22condit
@@ -1472,36 +1472,35 @@
 e);%0A            
-json
+ret
 .addProperty(%22tr
@@ -1574,20 +1574,19 @@
         
-json
+ret
 .addProp
@@ -1654,20 +1654,19 @@
  return 
-json
+ret
 ;%0A      
@@ -1660,32 +1660,33 @@
 n ret;%0A        %7D
+ 
 else %7B%0A         

fix by comments