package cz.cuni.amis.pogamut.base.communication.connection.socket;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.logging.Level;

import com.google.inject.Inject;

import cz.cuni.amis.pogamut.base.communication.connection.AbstractConnection;
import cz.cuni.amis.pogamut.base.communication.exceptions.ConnectionException;
import cz.cuni.amis.pogamut.base.factory.guice.AgentScoped;
import cz.cuni.amis.pogamut.base.utils.logging.AgentLogger;

@AgentScoped
public class SocketConnection extends AbstractConnection<ISocketConnectionAddress> {
	
	private Socket socket = null;
	
	private InputStreamReader socketReader = null;
	
	private OutputStreamWriter socketWriter = null;
		
	@Inject
	public SocketConnection(AgentLogger logger) {
		super(logger);
	}

	@Override
	protected Reader getConnectionReader() throws ConnectionException {
		return socketReader;
	}

	@Override
	protected Writer getConnectionWriter() throws ConnectionException {		
		return socketWriter;
	}

	@Override
	protected void unsyncClose() {
		if (socket != null) {
			try {
				socket.close();
			} catch (Exception e) {
				log(Level.SEVERE, "SocketConnection: can't close socket - " + e.getMessage());
			}
			try {
				socketReader.close();
			} catch (Exception e) {
				log(Level.SEVERE, "SocketConnection: can't close socket reader - " + e.getMessage());
			}
			try {
				socketWriter.close();
			} catch (Exception e) {
				log(Level.SEVERE, "SocketConnection: can't close socket writer - " + e.getMessage());
			}
		}
	}

	@Override
	protected void unsyncConnect(ISocketConnectionAddress address) throws ConnectionException {
		socket = new Socket();
		try {
			socket.connect(new InetSocketAddress(address.getHost(), address.getPort()));
			socketReader = new InputStreamReader(socket.getInputStream());
			socketWriter = new OutputStreamWriter(socket.getOutputStream());
		} catch (IOException e) {
			throw new ConnectionException(e.getMessage(), e, log);
		}
	}

}
