import java.net.ServerSocket;
import java.net.Socket;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;

public class CompressorServer extends Thread {
    private int port;
    private boolean isRunning = false;
    private ServerSocket serverSocket;

    public CompressorServer(int port) {
	this.port = port;
    }

    public int getPort() {
	return port;
    }

    public void run() {
	try {
	    isRunning = true;
	    serverSocket = new ServerSocket(4444);

	    while (true) {
		System.out.println("waiting for client...");
		new CompressorServerThread(serverSocket.accept()).start();
	    }
	} catch (Exception e) { 
	    //do nothing or log exception occured
	} finally {
	    isRunning = false;
	    try {
		serverSocket.close();
	    } catch (Exception e) {}
	}
    }

    public void startServer() throws Exception {
	start();
    }

    public void stopServer() {
	try {
	    serverSocket.close();
	} catch (Exception e) {}
    }

    public boolean isRunning() {
	return isRunning;
    }

    class CompressorServerThread extends Thread {
	private Socket clientSocket;

	public CompressorServerThread(Socket clientSocket) {
	    this.clientSocket = clientSocket;
	}

	public void run() {
	    try {
		processCommand();
	    } catch(Exception e) {
		throw new RuntimeException();
	    }
	}

	private void processCommand() throws Exception {
	    byte[] command = getCommand();

	    OutputStream output = clientSocket.getOutputStream();

	    ByteArrayOutputStream responseStream = 
	            new ByteArrayOutputStream();
	    try {
		if (echo(command)) {
		    responseStream.write(command, 4, command.length);
		    output.write(responseStream.toByteArray());
		}
	    } finally {
		try {
		    responseStream.close();
		} catch (Exception e) {}

		try {
		    output.close();
		} catch (Exception e) {}

		try {
		    clientSocket.close();
		} catch(Exception e) {}
	    }
	}

	private byte[] getCommand() throws IOException {
	    InputStream input = clientSocket.getInputStream();
	    ByteArrayOutputStream commandStream = new ByteArrayOutputStream();
	    
	    try {
		byte[] buf = new byte[1024];
		while (true) {
		    int bytesRead = input.read(buf);

		    if (bytesRead == -1) {
			break;
		    }
		    commandStream.write(buf, 0, bytesRead);
		}
	        byte[] command = commandStream.toByteArray();

		return command;
	    } finally {
		try {
		    input.close();
		} catch (Exception e) {}

		try {
		    commandStream.close();
		} catch (Exception e) {}
	    }
	}

	private boolean echo(byte[] command) {
	    if (command[0] == 'e' && command[1] == 'c' && command[2] == 'h'
		    && command[3] == 'o') {
		return true;
	    }

	    return false;
	}
    }
}



