package com.github.aureliano.achmed.server;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.util.logging.Logger;

import com.github.aureliano.achmed.common.exception.AchmedException;
import com.github.aureliano.achmed.common.helper.StringHelper;
import com.github.aureliano.achmed.common.logging.LoggingFactory;
import com.github.aureliano.achmed.server.service.IService;
import com.github.aureliano.achmed.server.service.ServiceFactory;
import com.github.aureliano.achmed.server.service.ServiceType;

public class ThreadHandler implements Runnable {
	
	private static final String SERVICE_PATTERN = "^service:\\s*";
	private static final String SERVICE_NAME_PATTERN = SERVICE_PATTERN + "(read_file)$";
	private static final Logger logger = LoggingFactory.createLogger(ThreadHandler.class);
	
	private Socket socket;
	
	private ThreadHandler(Socket socket) {
		this.socket = socket;
	}
	
	public static Runnable handle(Socket socket) {
		logger.info("Accepted connection from: " + socket.getInetAddress().getHostAddress());
		return new ThreadHandler(socket);
	}
	
	@Override
	public void run() {
		IService service = this.createService();
		service.consume(this.socket);
		this.closeSocket();
	}
	
	private IService createService() {
		ServiceType type = this.getServiceType();
		logger.info("Accessing service: " + type);
		return ServiceFactory.createService(type);
	}
	
	private ServiceType getServiceType() {
		String serviceName = this.getRequestedService();
		try {
			return ServiceType.valueOf(serviceName);
		} catch (Exception ex) {
			throw new AchmedException("There is not a service named " + serviceName);
		}
	}
	
	private String getRequestedService() {
		try {
			BufferedReader reader = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
			String requestedService = reader.readLine();
		
			if ((StringHelper.isEmpty(requestedService)) || (!requestedService.matches(SERVICE_NAME_PATTERN))) {
				throw new AchmedException("Broken service name description.");
			}
			
			String serviceName = requestedService.replaceFirst(SERVICE_PATTERN, "").trim();
			return serviceName.toUpperCase();
		} catch (IOException ex) {
			throw new AchmedException(ex);
		}
	}
	
	private void closeSocket() {
		if (!this.socket.isClosed()) {
			try {
				this.socket.close();
			} catch (IOException ex) {
				throw new AchmedException(ex);
			}
			logger.info("Closed connection.");
		}
	}
}
@@ -155,16 +155,48 @@
 Socket;%0A
+import java.util.logging.Level;%0A
 import j
@@ -1204,16 +1204,25 @@
 run() %7B%0A
+%09%09try %7B%0A%09
 %09%09IServi
@@ -1258,16 +1258,17 @@
 ce();%0A%09%09
+%09
 service.
@@ -1289,16 +1289,21 @@
 ocket);%0A
+%09%09%09%0A%09
 %09%09this.c
@@ -1316,16 +1316,103 @@
 cket();%0A
+%09%09%7D catch (AchmedException ex) %7B%0A%09%09%09logger.log(Level.SEVERE, ex.getMessage(), ex);%0A%09%09%7D%0A
 %09%7D%0A%09%0A%09pr

Handle error.