package cz.cuni.amis.pogamut.base.communication.commands;

import java.io.PrintWriter;

import com.google.inject.Inject;

import cz.cuni.amis.pogamut.base.communication.connection.IWorldWriterProvider;
import cz.cuni.amis.pogamut.base.communication.connection.socket.SocketConnection;
import cz.cuni.amis.pogamut.base.communication.exceptions.CommandException;
import cz.cuni.amis.pogamut.base.communication.exceptions.CommunicationException;
import cz.cuni.amis.pogamut.base.communication.exceptions.ConnectionException;
import cz.cuni.amis.pogamut.base.communication.messages.CommandMessage;
import cz.cuni.amis.pogamut.base.factory.guice.AgentScoped;
import cz.cuni.amis.pogamut.base.utils.logging.AgentLogger;
import cz.cuni.amis.pogamut.base.utils.logging.LogCategory;
import cz.cuni.amis.utils.listener.Listeners;

@AgentScoped
public class CommandSerializer implements ICommandSerializer {
	
	private PrintWriter writer = null;
	
	private IWorldWriterProvider writerProvider;
	
	protected AgentLogger agentLogger;
	
	protected LogCategory log;
	
	@Inject
	public CommandSerializer(IWorldWriterProvider writerProvider, AgentLogger logger) {
		agentLogger = logger;
		log = agentLogger.out();
		this.writerProvider = writerProvider;
	}
	
	public void start() throws ConnectionException {		
		writer = new PrintWriter(writerProvider.getWriter());
	}

	@Override
	public void stop() {
		writer.close();		
	}
	
	@Override
	public void kill() {
		stop();
	}
	
	/**
	 * Method that serialize the command to String.
	 * <p><p>
	 * Default implemnetation is appending SocketConnection.DEFAULT_LINE_END after each command.toMessage(). 
	 * @param command
	 * @return
	 */
	protected String serializeCommand(CommandMessage command) {
		return command.toMessage() + SocketConnection.DEFAULT_LINE_END;
	}
	
	/**
	 * Sends command through the writer.
	 * 
	 * @param command
	 * @throws CommunicationException
	 */
	public void sendCommand(CommandMessage command) throws CommunicationException {
		log.fine("Sending command: " + command);
		if (writer == null) throw new CommandException("Writer not initialized, start() not called?", log, this);
		writer.print(serializeCommand(command));
		writer.flush();
	}

}
