import java.net.URI;
import java.util.concurrent.TimeUnit;

import javax.swing.JFrame;
import javax.swing.JOptionPane;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import io.socket.client.IO;
import io.socket.client.Socket;
import io.socket.emitter.Emitter;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Client {
	Socket socket;
	Stage primaryStage;
	Client client;

	public Client(Stage primaryStage) {
		this.client = this;
		this.primaryStage = primaryStage;
		socket = IO.socket(URI.create("http://messagingappsoftwareeng.herokuapp.com"));
		socket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {

			@Override
			public void call(Object... args) {
				System.out.println("Connected to server!");
				socket.emit("hello", " world");
			}
		});
		socket.on("hello", new Emitter.Listener() {

			@Override
			public void call(Object... args) {
				JSONObject response = (JSONObject) args[0];
				try {
					System.out.println("Hello " + response.getString("hello"));
				} catch (JSONException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}

		});

		socket.on("users", new Emitter.Listener() {

			@Override
			public void call(Object... args) {
				System.out.println(args[0]);
				Platform.runLater(new Runnable() {
					@Override
					public void run() {
						App.activeUsers.clear();
						JSONArray jsonArray = (JSONArray) args[0];
						String[] users = toStringArray(jsonArray);
						if (users != null && users.length > 0)
						{
							for (int i = 0; i < users.length; i++) {
								if (users[i].equals(App.username)) {
									continue;
								}
								else {
									App.activeUsers.add(users[i]);
								}
							}
							MainLobby.updateUsers();
						}
					}
				});
			}

		});

		socket.on("message", new Emitter.Listener() {

			@Override
			public void call(Object... args) {
				App.messages.add((String) args[0]);
				MainLobby.updateMessages((String) args[0]);
			}

		});
		
		socket.on("privateMessage", new Emitter.Listener() {

			@Override
			public void call(Object... args) {
				System.out.println((String)args[0]);
				System.out.println((String)args[1]);
				Platform.runLater(new Runnable() {
					@Override
					public void run() {
						String username = (String) args[0];
		            	if (MainLobby.privateMessageWindows.get(username) != null && MainLobby.privateMessageWindows.containsKey(username)) {
		            		MainLobby.privateMessageWindows.get(username).show();
		            		MainLobby.privateMessageWindows.get(username).updateMessages((String) args[1]);
		            	}
		            	else {
		            		MainLobby.privateMessageWindows.put(username, new Conversation(username, client));
		            		MainLobby.privateMessageWindows.get(username).updateMessages((String) args[1]);
		            	}
					}
				});
				
			}

		});
		
		socket.on("messages", new Emitter.Listener() {

			@Override
			public void call(Object... args) {
				String messages = "";
				JSONArray msgs = (JSONArray)args[0];
				for (int i = 0; i < msgs.length(); i++) {
					try {
						messages += msgs.optJSONObject(i).getString("message") + "\n";
					} catch (JSONException e) {
						break;
					}
				}

				try{

					  Thread.sleep(2000);
					}catch(InterruptedException ex){
					  //do stuff
					}
				MainLobby.updateMessages(messages);
			}

		});

		socket.on("registered", new Emitter.Listener() {

			@Override
			public void call(Object... args) {
				System.out.println("Registration successful " + args[0]);
				Platform.runLater(new Runnable() {
					@Override
					public void run() {
						new MessageBox("Registered", "Successfully registered with username '" + (String) args[0]
								+ "'.\n You can log in now!");
					}
				});

			}

		});

		socket.on("registerError", new Emitter.Listener() {

			@Override
			public void call(Object... args) {
				System.out.println("Couldn't register: " + args[0]);
				Platform.runLater(new Runnable() {
					@Override
					public void run() {
						new MessageBox("Register Error", (String) args[0]);
					}
				});

			}

		});

		socket.on("loggedIn", new Emitter.Listener() {

			@Override
			public void call(Object... args) {
				System.out.println("Login successful " + args[0]);
				Platform.runLater(new Runnable() {
					@Override
					public void run() {
						App.username = (String) args[0];
						new MainLobby(primaryStage, client);
					}
				});

			}

		});

		socket.on("logInError", new Emitter.Listener() {

			@Override
			public void call(Object... args) {
				System.out.println("Couldn't login: " + args[0]);
				Platform.runLater(new Runnable() {
					@Override
					public void run() {
						new MessageBox("Login Error", (String) args[0]);
					}
				});
			}

		});
		socket.connect();
	}

	public void register(String username, String password) {
		socket.emit("register", username + "," + password);
	}

	public void login(String username, String password) {
		socket.emit("login", username + "," + password);
	}

	public void message(String message) {
		socket.emit("message", message);
	}

	public void privateMessage(String message, String to) {
		socket.emit("privateMessage", message, to);
	}

	public void disconnect() {
		socket.disconnect();
	}
	
	public static String[] toStringArray(JSONArray array) {
	    if(array==null)
	        return null;

	    String[] arr=new String[array.length()];
	    for(int i=0; i<arr.length; i++) {
	        arr[i]=array.optString(i);
	    }
	    return arr;
	}
}
