package com.framsticks.net.client3D;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.ArrayList;

/**
 * Communication class.
 * @author MoMaT (modified by vorg @ 2007/01/25)
 */
public class Communication {
	private Socket socket = null;
	private PrintWriter out = null;
	private BufferedReader in = null;
	protected boolean connected = false;

	private ArrayList<String> log = new ArrayList<String>();
	 	
	/**
	 * Connect to a server.
	 * @param ip
	 * @param port
	 * @throws IOException Thrown on I/O error.
	 */	
	public void connect(String ip, int port) throws IOException {
		try {
			socket = new Socket(ip, port);
			out = new PrintWriter(socket.getOutputStream(), true);
			in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			
			connected = true;
			sendMessage("version 3");
			String message = in.readLine();
			log.add(">  " + message);
			
		}
		catch(Exception e) {
			Log.getInstance().log("err", e.toString());
		}
	}
	/**
	 * Close connection.
	 * @throws IOException Thrown on socket close error.
	 */
	public void disconnect() throws IOException {	
		connected = false;
		out.close();
		in.close();
		socket.close();
	}				
	/**
	 * Read a server response.
	 * @return server answer
	 * @throws IOException Thrown on read error.
	 * @throws InterruptedException Thrown on thread sleep interruption.
	 * @throws CommunicationErrorException Thrown on protocol error.
	 */
  	public ArrayList<String> readMessage()
  	throws IOException, InterruptedException, CommunicationErrorException {		
  		if (!connected) {
			Log.getInstance().log("wrn", "Reading message failed. You are not connected!");
			return new ArrayList<String>();
		}
	  	String message = null;
		ArrayList<String> buffer = new ArrayList<String>();

		//gentle wait for input on socket
		//elapsedTime added by vorg to avoid infinite loop
		int elapsedTime = 0;
		while (false == in.ready()) {
			Thread.sleep(100);
			elapsedTime++;
			if (elapsedTime > 100) {
				throw new InterruptedException("Request timeout");
			}
		}

		//read server answer			
	  	while ((message = in.readLine()) != null) {				
			log.add("> " + message);
			//stop if reading complete
			if(message.startsWith("ok")) {
				//add ok line if it contains additional info
				if (3 < message.length()) {
					buffer.add(message);
				}				
				break;
			} else if (message.startsWith("error")) {
				String error = message.substring(message.indexOf(' '));
				throw new CommunicationErrorException(error);
	  		}				
			buffer.add(message);					
		}
		return buffer;
  	}										  																																			
	/**
	 * Send request to a server. 
 	 * @param message
 	 */
	public void sendMessage(String message) {
		Log.getInstance().log(">>>", message);
		log.add(message);
		if (!connected) {
			Log.getInstance().log("wrn", "Sending message failed. You are not connected!");
			return;
		}
		out.println(message);
	}			
	/**
	 * Log getter.
	 * @return log array
	 */
	public ArrayList<String> getLog() {
		return log;
	}
	
	public Boolean isConnected() {
		return connected;
	}
}

