package com.xikka.client;

import java.awt.Dimension;
import java.awt.event.ActionListener;
import java.util.concurrent.Future;
import java.util.function.Function;

import javax.swing.BoxLayout;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.ListSelectionModel;

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

import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.JsonNode;
import com.mashape.unirest.http.async.Callback;
import com.mashape.unirest.http.exceptions.UnirestException;

class RoomsPanel extends JPanel implements SelectablePanel {
	private static final long serialVersionUID = 7993365654825410556L;

	private static class Session {
		private final long id;
		private Session(long i) {
			id = i;
		}
		public String toString() {
			return "Session " + id;
		}
	}
	
	private final JList<Session> sessionList;
	private final DefaultListModel<Session> sessionListModel;
	private final Function<Long, Void> onSelectSession;
	
	private final JButton searchButton = new JButton();
	private Future<HttpResponse<JsonNode>> searchResp;
	private long matchmakingId = -1;
	private final ActionListener searchListener = a -> {
		try {
			HttpResponse<JsonNode> resp = GameClientMain
					.post("games/{game}/matchmaking")
					.asJson();
			
			GameClientMain.handleErrorResponses(resp);
			System.out.println(resp.getBody());
			if (GameClientMain.isSuccessfulResponse(resp)) {
				JSONObject o = resp.getBody().getObject();
				matchmakingId = o.getLong("id");
				setButtonMode(false);
				// Start waiting for matchmaking response in a new thread...
				searchResp = GameClientMain
						.get("games/{game}/matchmaking/{id}")
						.routeParam("id", String.valueOf(matchmakingId))
						.asJsonAsync(new Callback<JsonNode>() {
							@Override
							public void cancelled() {
								System.out.println("Cancelled.");
							}

							@Override
							public void completed(HttpResponse<JsonNode> resp) {
								System.out.println("Body: " + resp.getBody());
								GameClientMain.handleErrorResponses(resp);
								if (GameClientMain.isSuccessfulResponse(resp)) {
									// Go straight to the session
									long id = resp.getBody().getObject().getLong("id");
									onSelectSession.apply(id);
								}
							}

							@Override
							public void failed(UnirestException resp) {
								// TODO Auto-generated method stub
								
							}
						});
				// Change button to "Stop"
			}
		} catch (Exception e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}	
	};
	private final ActionListener stopListener = a -> {
		try {
			GameClientMain
					.delete("games/{game}/matchmaking/{id}")
					.routeParam("id", String.valueOf(matchmakingId))
					.asString();
			//GameClientMain.handleErrorResponses(resp);
			
			// Stop the searching thread
			setButtonMode(true);
			searchResp.cancel(true);
		} catch (Exception e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}	
	};
	
	RoomsPanel(Function<Long, Void> onSelectSession) {
		this.onSelectSession = onSelectSession;
		setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
		
		setButtonMode(true);
		add(searchButton);
		
		sessionListModel = new DefaultListModel<Session>();
		sessionList = new JList<Session>(sessionListModel);
		sessionList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		sessionList.setPreferredSize(new Dimension(100, 200));
		add(sessionList);
		
		JButton ok = new JButton();
		ok.setText("Select session");
		ok.addActionListener(a -> {
			onSelectSession.apply(sessionList.getSelectedValue().id);
		});
		add(ok);
	}
	
	public void onSelect() {
		sessionListModel.removeAllElements();
		// Get list of sessions for this user
		try {
			HttpResponse<JsonNode> resp = GameClientMain
					.get("games/{game}/sessions")
					.asJson();
			System.out.println("Body: "+resp.getBody().toString());
			JSONArray a = resp.getBody().getArray();
			for (int i = 0; i < a.length(); i++) {
				JSONObject o = a.getJSONObject(i);
				sessionListModel.addElement(new Session(o.getLong("sessionId")));
			}
		} catch (UnirestException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		if (! sessionListModel.isEmpty())
			sessionList.setSelectedIndex(0);
	}
	
	private void setButtonMode(boolean search) {
		searchButton.removeActionListener(searchListener);
		searchButton.removeActionListener(stopListener);
		if (search) {
			searchButton.setText("Look for players...");
			searchButton.addActionListener(searchListener);
		} else {
			searchButton.setText("Stop");
			searchButton.addActionListener(stopListener);
		}
	}
}
