package org.btcollider.cnc.comm;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class CommServer {
	final Logger log = LoggerFactory.getLogger(CommServer.class);

	private int port;
	private ServerSocket serverSocket;

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

	public void listen() throws CommException {
		if(serverSocket == null || serverSocket.isClosed()) {
			openSocket();
		}
		
		ExecutorService es = Executors.newCachedThreadPool();

		while (true) {
			try {
				Socket socket = serverSocket.accept();
				log.debug("Got connection from " + socket.getInetAddress());
				es.execute(new ClientWorker(socket));

			} catch (IOException e) {
				log.error("Couldn't establish connections on socket", e);
				throw new CommException(e);
			}
		}
	}

	public void stop() {
		closeSocket();
	}

	private void openSocket() throws CommException {
		log.debug("Opening socket on port {}", port);

		try {
			this.serverSocket = new ServerSocket(port);
		} catch (IOException e) {
			log.error("Couldn't allocate server socket", e);

		}
	}

	private void closeSocket() {
		if (this.serverSocket != null && !this.serverSocket.isClosed()) {
			try {
				serverSocket.close();
			} catch (IOException e) {
				log.error("Couldn't close server socket cleanly", e);
			}
		}
	}
}
