package aalg.mailer;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
import aalg.algebra.VariableNumberIo;

public class PersistableFactory<T extends IPersistable> {

	private final Map<Integer, IInstanceCreator<? extends T>> idToCreatorMap = new HashMap<>();
	private final Map<Class<? extends T>, Integer> classToIdMap = new HashMap<>();
	
	protected <S extends T> void registerClass (final int id, final Class<S> clazz) {
		registerClass(id, clazz, new ReflectionInstanceCreator<S>(clazz));
	}
	
	protected <S extends T> void registerClass (final int id, final Class<S> clazz, final IInstanceCreator<S> creator) {
		if (idToCreatorMap.containsKey(id) || classToIdMap.containsKey(clazz))
			throw new RuntimeException("ID or class already registered");
		
		idToCreatorMap.put(id, creator);
		classToIdMap.put(clazz, id);
	}
	
	public void write (final OutputStream stream, final T obj) throws IOException {
		final Class<? extends IPersistable> clazz = obj.getClass();
		final int id = classToIdMap.get(clazz);
		
		VariableNumberIo.writeInt(id, stream);
		obj.write(stream);
	}
	
	public T read (final InputStream stream) throws IOException {
		final int id = VariableNumberIo.readInt(stream);
		final IInstanceCreator<? extends T> creator = idToCreatorMap.get(id);
		final T obj = creator.createInstance();
		obj.read(stream);
		
		return obj;
	}
}
