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

import java.io.IOException;
import java.io.Reader;

import com.google.inject.Inject;

import cz.cuni.amis.pogamut.base.communication.connection.IWorldReaderProvider;
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.exceptions.ParserException;
import cz.cuni.amis.pogamut.base.communication.messages.InfoMessage;
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;

@AgentScoped
public class Parser implements IWorldMessageParser {
	
	private IWorldReaderProvider readerProvider;
	
	private Reader reader = null;
	
	private IYylex yylex;
	
	private AgentLogger agentLogger = null;
	
	private LogCategory log = null;
	
	@Inject
	public Parser(IWorldReaderProvider readerProvider, IYylex yylex, AgentLogger logger) throws CommunicationException {
		agentLogger = logger;
		log = agentLogger.in();
		this.readerProvider = readerProvider;
		this.yylex = yylex;
		this.yylex.setObserver(new IYylexObserver.LogObserver(logger));
	}
	
	@Override
	public void start() throws ConnectionException {
		this.reader = readerProvider.getReader();
		this.yylex.setReader(reader);		
	}

	@Override
	public void stop() {
		try {
			reader.close();
		} catch (Exception e) {
			log.severe("Parser: can't close parser's reader - " + e.getMessage());
		}
	}
	
	@Override
	public void kill() {
		stop();
	}

	@Override
	public InfoMessage parse() throws ParserException {
		try {
			InfoMessage parsed = yylex.yylex(); 
			return parsed;
		} catch (IOException e) {
			throw new ParserException("Can't parse next message: " + e.getMessage(), e, log, this);
		}
	}
	
	protected AgentLogger getLogger() {
		return agentLogger;
	}

}
