package pylos.network;

import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.URI;
import java.net.UnknownHostException;
import java.rmi.Naming;
import java.rmi.NoSuchObjectException;
import java.rmi.registry.LocateRegistry;
import java.rmi.server.UnicastRemoteObject;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;

import pylos.Config;
import pylos.model.Model;
import pylos.model.Player;

public class Network {
	static final String localhost = "localhost";
	static final String remoteHost = "localhost";
	static final String remoteObjectBaseName = "/RemotePylos";
	static String remoteObjectName;

	RemoteGameInterface localGame;
	public List<RemoteGameInterface> remoteGames = new LinkedList<RemoteGameInterface>();
	List<String> remoteObjectsNames = new LinkedList<String>();

	public boolean isPaired() {
		return !remoteGames.isEmpty();
	}

	private String rmiURL(String host) {
		return "//" + host + ":" + Config.RMI_PORT;
	}

	public void createConnections() {
		setRMIhostname(localhost);

		String uID = ManagementFactory.getRuntimeMXBean().getName();
		remoteObjectName = remoteObjectBaseName + uID; // + getIP() ?
		System.out.println(getIP());
		launchServer();
		scanForRemote(remoteHost); // TODO: ask the host
		scanForRemote(localhost);
	}

	/**
	 * equivalent of command line arg -Djava.rmi.server.hostname=myhostname
	 */
	private void setRMIhostname(String hostname) {
		Properties systemProperties = new Properties(System.getProperties());
		systemProperties.put("java.rmi.server.hostname", hostname);
		System.setProperties(systemProperties);
	}

	private void launchServer() {
		try {
			FutureTask<?> startRegistry = new FutureTask<Void>(new Callable<Void>() {
				public Void call() throws Exception {
					System.out.println("Searching or creating the rmiregistry ...");
					LocateRegistry.createRegistry(Config.RMI_PORT);
					System.out.println("Created the registry");
					return null;
				}
			});
			new Thread(startRegistry).start();
			startRegistry.get(Config.CREATE_RMI_REGISTRY_TIMEOUT, TimeUnit.MILLISECONDS);
		} catch (Exception e) {
			// Already Running
		}

		try {
			String url = rmiURL(localhost) + remoteObjectName;
			RemoteGameInterface localGame = new RemoteGame();
			Naming.rebind(url, localGame);
			this.localGame = localGame;
			System.out.println("Server is ready: " + url);
		} catch (Exception e) {
			System.out.println("Server failed: " + e);
		}
	}

	public void scanForRemote(String host) {
		try {
			String base = rmiURL(host);
			String[] list = Naming.list(base);

			System.out.println(base);
			System.out.println(list.length);
			for (String remoteName : list) {
				System.out.println(remoteName);
				String path = (new URI(remoteName)).getPath();
				try {
					if (!path.equals(remoteObjectName) && !remoteObjectsNames.contains(path)) {
						String url = base + path;
						RemoteGameInterface remoteGame = (RemoteGameInterface) Naming.lookup(url);
						remoteGames.add(remoteGame);
						remoteObjectsNames.add(path);
						System.out.println("Paired with " + url);

						if (Model.player1.isUndefined() && Model.player2.isUndefined()) {
							byte player = remoteGame.askForPlayer();
							if (player != 0) {
								Player me = Player.fromByte(player);
								me.isLocal();
								me.other().isRemote();
							}
						}

						remoteGame.scanForRemote(getIP()); // TODO: be able to specify own's ip
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private String getIP() {
		try {
			return InetAddress.getLocalHost().getHostAddress();
		} catch (UnknownHostException e) {
			System.err.println("Could not get ip: " + e);
			return null;
		}
	}

	public void stop() {
		if (localGame != null) {
			try {
				Naming.unbind(remoteObjectName);
			} catch (Exception e) {
			}

			try {
				UnicastRemoteObject.unexportObject(localGame, true);
			} catch (NoSuchObjectException e) {
			}

		}
	}
}

@@ -84,78 +84,11 @@
 net.
-InetAddress;%0Aimport java.net.URI;%0Aimport java.net.UnknownHostException
+URI
 ;%0Aim
@@ -559,33 +559,35 @@
 ocalhost = %22
-localhost
+192.168.0.2
 %22;%0A%09static f
@@ -612,25 +612,27 @@
 Host = %22
-localhost
+192.168.0.3
 %22;%0A%09stat
@@ -1268,23 +1268,25 @@
 println(
-getIP()
+localhost
 );%0A%09%09lau
@@ -3460,23 +3460,25 @@
 rRemote(
-getIP()
+localhost
 ); // TO
@@ -3636,24 +3636,31 @@
 );%0A%09%09%7D%0A%09%7D%0A%0A%09
+/*%0A%09 * 
 private Stri
@@ -3673,26 +3673,29 @@
 IP() %7B%0A%09
-%09
+ * 
 try %7B%0A%09
-%09%09
+ * 
 return I
@@ -3735,25 +3735,27 @@
 Address();%0A%09
-%09
+ * 
 %7D catch (Unk
@@ -3774,26 +3774,27 @@
 ption e) %7B%0A%09
-%09%09
+ * 
 System.err.p
@@ -3828,18 +3828,19 @@
  + e);%0A%09
-%09%09
+ * 
 return n
@@ -3845,21 +3845,31 @@
  null;%0A%09
-%09%7D%0A%09%7D
+ * %7D%0A%09 * %7D%0A%09 */
 %0A%0A%09publi

use only hard coded local ip (debug mode on)