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

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.Writer;
import java.net.Socket;
import java.net.UnknownHostException;

import org.junit.Test;

import cz.cuni.amis.pogamut.base.communication.connection.socket.ISocketConnectionAddress;
import cz.cuni.amis.pogamut.base.communication.connection.socket.SocketConnection;
import cz.cuni.amis.pogamut.base.communication.connection.socket.SocketConnectionAddress;
import cz.cuni.amis.pogamut.base.communication.exceptions.ConnectionException;
import cz.cuni.amis.pogamut.base.utils.logging.AgentLogger;

import junit.framework.TestCase;

public class TestCase01_SocketConnection extends CommunicationTestCase {

	private String[] responses = new String[] { "Hello", "Bye" };

	public String[] getResponses() {
		return responses;
	}

	/**
	 * Connects and send GET, check response and send QUIT.
	 * <p>
	 * <p>
	 * Using SocketConnection + only once initialized Reader and Writer.
	 * <p>
	 * <p>
	 * Doing 10 iterations of connection/reading/writing/closing while reader
	 * and writer remains the same (also reusing SocketConnection object!).
	 */
	@Test
	public void test01_SocketConnection() {

		SocketConnection conn = new SocketConnection(new AgentLogger());
		assertTrue(
				"connection is connected???, should not be, isConnected() == true",
				!conn.isConnected());

		BufferedReader in = null;
		PrintWriter out = null;
		try {
			in = new BufferedReader(conn.getReader());
		} catch (ConnectionException e) {
			fail("can't get reader for the connection: " + e.getMessage());
		}
		try {
			out = new PrintWriter(conn.getWriter());
		} catch (ConnectionException e) {
			fail("can't get writer for the connection: " + e.getMessage());
		}

		for (int iter = 0; iter < 10; ++iter) {

			reinitServer();

			assertTrue("server not started correctly", getServer().consume(
					"Server started"));

			try {
				conn.connect(new SocketConnectionAddress("127.0.0.1", getServer().getPort()));
			} catch (ConnectionException e) {
				fail("can't connect to server: " + e.getMessage());
			}

			assertTrue("connection not connected, isConnected() == false", conn.isConnected());

			out.println(Server.GET_COMMAND);
			out.flush();

			try {
				int i = 0;
				while (in.ready()) {
					if (i >= getResponses().length) {
						fail("server sent too many response lines");
					}
					String line = in.readLine();
					assertTrue("wrong response, EXPECTED: " + getResponses()[i]
							+ ", GOT: " + line, line
							.equals(getResponses()[i++]));
				}
			} catch (IOException e) {
				fail("can't read whole response: " + e.getMessage());
			}

			out.println(Server.QUIT_COMMAND);
			out.flush();

			try {
				Thread.sleep(200);
			} catch (InterruptedException e) {
			}

			assertTrue("server didn't receive GET command", getServer()
					.consume("Received: " + Server.GET_COMMAND));
			for (String str : getResponses()) {
				assertTrue("server wrong reply", getServer().consume(
						"Sent: " + str));
			}
			assertTrue("server didn't receive QUIT command", getServer()
					.consume("Received: " + Server.QUIT_COMMAND));
			assertTrue("server didn't terminate", getServer().consume(
					"Server terminated"));

			conn.close();
			assertTrue("connection not closed", !conn.isConnected());

			assertTrue("some server output left", getServer().isClear(true));
		}
	}

}
