package ctbrec.io;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map.Entry;

import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.JsonReader;
import com.squareup.moshi.JsonReader.Token;
import com.squareup.moshi.JsonWriter;

import ctbrec.recorder.postprocessing.PostProcessor;

public class PostProcessorJsonAdapter extends JsonAdapter<PostProcessor> {

    @Override
    public PostProcessor fromJson(JsonReader reader) throws IOException {
        reader.beginObject();
        Object type = null;
        PostProcessor postProcessor = null;
        while(reader.hasNext()) {
            try {
                Token token = reader.peek();
                if(token == Token.NAME) {
                    String key = reader.nextName();
                    if(key.equals("type")) {
                        type = reader.readJsonValue();
                        Class<?> modelClass = Class.forName(type.toString());
                        postProcessor = (PostProcessor) modelClass.getDeclaredConstructor().newInstance();
                    } else if(key.equals("config")) {
                        reader.beginObject();
                    } else {
                        String value = reader.nextString();
                        postProcessor.getConfig().put(key, value);
                    }
                } else {
                    reader.skipValue();
                }
            } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) {
                throw new IOException("Couldn't instantiate post-processor class [" + type + "]", e);
            }
        }
        reader.endObject();
        reader.endObject();

        return postProcessor;
    }

    @Override
    public void toJson(JsonWriter writer, PostProcessor pp) throws IOException {
        writer.beginObject();
        writer.name("type").value(pp.getClass().getName());
        writer.name("config");
        writer.beginObject();
        for (Entry<String, String> entry : pp.getConfig().entrySet()) {
            writer.name(entry.getKey()).value(entry.getValue());
        }
        writer.endObject();
        writer.endObject();
    }

}
