package clientP2P;

import java.util.Scanner;
import java.util.List;
import clientP2P.ClientManagementUDP;
import clientP2P.ClientManagementTCP;
import serverP2P.ServerManagementUDP;
import serverP2P.ServerManagementTCP;
import tools.Logger;
import tools.LogLevel;
import tools.Directories;
import tools.HostItem;

/** Client + Server implementation.
 * @author	Louis Royer
 * @author	Flavien Haas
 * @author	JS Auge
 * @version	1.0
 */

public class ClientP2P {
	private String logDir = "logs/";
	private String partsDir = ".parts/";
	private Logger loggerServer;
	private Logger loggerClient;
	private String host;
	private int port;
	private Directories directories;
	private static final int defaultPort = 20000;
	private HostItem tracker;
	private Scanner scanner;


	/** Initialize loggers if directories and logger are null,
	 * else fail silently.
	 */
	public void initDirectoriesAndLoggers() {
		if (directories == null && loggerServer == null && loggerClient == null) {
			directories = new Directories("P2P_JAVA_PROJECT_" + port);
			directories.createSubdir(logDir);
			loggerServer = new Logger(directories.getDataHomeDirectory() + logDir + "server.log");
			loggerClient = new Logger(directories.getDataHomeDirectory() + logDir + "client.log");
			directories.createSubdir(partsDir);
		}
	}

	/** Constructor with portStr as parameter.
	 * @param portStr	String containing port for server listenning.
	 */
	public ClientP2P(String portStr) {
		scanner = new Scanner(System.in);
		tracker = new HostItem("localhost", 30000); // TODO : make it configurable
		try{
			port = Integer.valueOf(Integer.parseInt(portStr));
		} catch (NumberFormatException e){
			int oldPort = port;
			port = defaultPort;
			initDirectoriesAndLoggers();
			System.err.println("Error incorrect port " + oldPort + " using default port " + defaultPort);
			loggerServer.write("incorrect port " + oldPort + " using default port " + defaultPort, LogLevel.Info);
		}
		initDirectoriesAndLoggers();
		host = "localhost";
		System.out.println("Server will listen on port " + port + " and serve files from " + directories.getDataHomeDirectory());
		directories.askOpenDataHomeDirectory(null, scanner);
		System.out.println("Please enter list of servers to use; first one will be used to ask list of files");
	}

	/** Main program entry point.
	 * 1rst parameter is optionnal, and is used to
	 * define port used by the server module to listen. If not provided, default to another port.
	 * @param args	server listenning port
	 */
	public static void main(String [] args) {
		if (args[1].equals("help") || args[1].equals("-h") || args[1].equals("h")){
			System.out.println("usage : java clientP2P.ClientP2P or java clientP2P.ClientP2P -- <integratedServerPORT> <trackerHOSTNAME> <trackerPORT> (default for integratedServer localhost:7070 and tracker localhost:6969, range 7000 -> 7999)");
		}
		else{
			ClientP2P c;
			try {
				c = new ClientP2P(args[1]);
			} catch (IndexOutOfBoundsException e){
				c = new ClientP2P("" + defaultPort);
			}

			// Server threads
			ServerManagementUDP smudp = new ServerManagementUDP(c.directories.getDataHomeDirectory(), "localhost", c.port, c.loggerServer, c.tracker);
			ServerManagementTCP smtcp = new ServerManagementTCP(c.directories.getDataHomeDirectory(), "localhost", c.port, c.loggerServer, c.tracker);
			Thread tudp = new Thread(smudp);
			tudp.setName("server UDP P2P-JAVA-PROJECT (port: " + c.port + ")");
			tudp.start();
			Thread ttcp = new Thread(smtcp);
			ttcp.setName("server TCP P2P-JAVA-PROJECT (port: " + c.port + ")");
			ttcp.start();

			// Wait a bit before printing client interface
			// This is not required, but allow to have a cleaner interface
			try {
				Thread.sleep(200);
			} catch(InterruptedException e) {
				Thread.currentThread().interrupt();
			}

			// initialize Host lists
			System.out.println("Client : Which transport protocol do you want to use? [TCP/udp]");
			c.scanner.hasNextLine();
			String transportchoosen = c.scanner.nextLine();
			Thread t;
			switch(transportchoosen){
				case "UDP":
				case "udp":
				case "upd": // alias typo
				case "2" :
					System.out.println("Starting with UDP");
					ClientManagementUDP cmudp = new ClientManagementUDP(c.directories.getDataHomeDirectory(), c.tracker, c.directories.getDataHomeDirectory() + c.partsDir, c.loggerClient, c.scanner);
					t = new Thread(cmudp);
					break;
				case "TCP":
				case "tcp":
				case "1":
				default:
					System.out.println("Starting with TCP");
					ClientManagementTCP cmtcp = new ClientManagementTCP(c.directories.getDataHomeDirectory(), c.tracker, c.directories.getDataHomeDirectory() + c.partsDir, c.loggerClient, c.scanner);
					t = new Thread(cmtcp);
					break;
				}
			t.setName("client P2P-JAVA-PROJECT");
			t.start();
			try {
				t.join();
			} catch (InterruptedException e) {}
			c.scanner.close();
			smudp.setStop();
			smtcp.setStop();
			
		}
	}
}
