package com.bernard.greposimu.model.game;

import java.io.IOException;

import com.bernard.greposimu.model.game.researches.Research;
import com.bernard.greposimu.model.game.units.Hero;
import com.bernard.greposimu.model.game.units.Unit;
import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.KeyDeserializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;

public class GrepoYaml extends SimpleModule {
    
    GameConfig gc;

    public GrepoYaml(GameConfig gc) {
        this.gc = gc;
        registerId(Unit.class);
        registerId(Research.class);
        registerId(Building.class);
        registerId(God.class);
        registerId(Hero.class);
    }

    private <T extends Identified> void registerId(Class<T> clazz){
        this.addSerializer(clazz, new IdSerializer<T>());
        this.addKeySerializer(clazz, new IdKeySerializer<T>());
        this.addDeserializer(clazz, new IdDeserializer<T>(clazz));
        this.addKeyDeserializer(clazz, new IdKeyDeserializer<T>(clazz));
    }

    public class IdSerializer<T extends Identified> extends JsonSerializer<T>{
        @Override
        public void serialize(T value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
            gen.writeString(value.getId());
        }
    }
    public class IdKeySerializer<T extends Identified> extends JsonSerializer<T>{
        @Override
        public void serialize(T value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
            gen.writeFieldName(value.getId());
        }
    }

    public class IdDeserializer<T extends Identified> extends JsonDeserializer<T> {

        Class<T> clazz;

        public IdDeserializer(Class<T> clazz) {
            this.clazz = clazz;
        }

        @Override
        public T deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException {
            String id = p.getText();
            return gc.getIdentified(clazz, id);
        }
    }
    public class IdKeyDeserializer<T extends Identified> extends KeyDeserializer {

        Class<T> clazz;

        public IdKeyDeserializer(Class<T> clazz) {
            this.clazz = clazz;
        }

        @Override
        public Object deserializeKey(String key, DeserializationContext ctxt) throws IOException {
            return gc.getIdentified(clazz, key);
        }
    }
}
