package com.xikka.client;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

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.exceptions.UnirestException;

public class NoughtsSessionPanel extends JPanel implements SelectablePanel, StoppablePanel {
	private static final long serialVersionUID = 1236888169367325424L;
	private final long sessionId;
	private String[] grid;
	private final JButton buttons[] = new JButton[9];
	private boolean running;
	private long lastEventId = -1;
	
	NoughtsSessionPanel(long sessionId) {
		this.sessionId = sessionId;
		
		setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
		
		// Three rows of three buttons each
		JPanel top = new JPanel();
		JPanel middle = new JPanel();
		JPanel bottom = new JPanel();
		add(top);
		add(middle);
		add(bottom);
		
		for (int i = 0; i < 3; i++) {
			final int j = i;
			{
				JButton b = new JButton();
				b.setText("");
				b.addActionListener(a -> doTurn(j));
				top.add(b);
				buttons[0 + i] = b;
			}
			{
				JButton b = new JButton();
				b.setText("");
				b.addActionListener(a -> doTurn(3 + j));
				middle.add(b);
				buttons[3 + i] = b;
			}
			{
				JButton b = new JButton();
				b.setText("");
				b.addActionListener(a -> doTurn(6 + j));
				bottom.add(b);
				buttons[6 + i] = b;
			}
		}
		
		//
	}
	
	private void doTurn(int cell) {
		try {
			JSONObject turn = new JSONObject();
			turn.put("cell", cell);
			HttpResponse<JsonNode> resp = GameClientMain
					.post("games/{game}/sessions/{session-id}/turn")
					.routeParam("session-id", String.valueOf(sessionId))
					.header("content-type", "application/json")
					.body(turn)
					.asJson();
			GameClientMain.handleErrorResponses(resp);
		} catch (UnirestException e) {
			e.printStackTrace();
		}
	}
	
	private String getOorX(String p) {
		if ("0".equals(p))
			return "O";
		else if ("1".equals(p))
			return "X";
		return "";
	}
	
	private void drawGrid() {
		for (int i = 0; i < grid.length; i++) {
			String text = getOorX(grid[i]);
			buttons[i].setText(text);
		}
	}
	
	private long getSession() {
		try {
			HttpResponse<JsonNode> resp = GameClientMain
					.get("games/{game}/sessions/{session-id}")
					.routeParam("session-id", String.valueOf(sessionId))
					.asJson();
			System.out.println(resp.getBody());
			GameClientMain.handleErrorResponses(resp);
			JSONObject e = resp.getBody().getObject();
			String gridString = e.getJSONObject("environment").getString("grid");
			grid = gridString.split("");
			if (grid != null) {
				drawGrid();
			}
			return e.getLong("toEventId");
		} catch (UnirestException e) {
			e.printStackTrace();
		}
		return -1;
	}
	
	@Override
	public void onStop() {
		running = false;
	}

	@Override
	public void onSelect() {
		// Get session!
		lastEventId = getSession();
		
		// Start listening for events on a new thread
		// When the response comes in, start listening again!
		running = true;
		new Thread(() -> {
			while (running) {
				try {
					HttpResponse<JsonNode> resp = GameClientMain
							.get("games/{game}/sessions/{session-id}/events")
							.routeParam("session-id", String.valueOf(sessionId))
							.queryString("after-event-id", lastEventId)
							.asJson();
					GameClientMain.handleErrorResponses(resp);
					System.out.println("Events received: " + resp.getBody().toString());
					JSONArray events = resp.getBody().getArray();
					for (int i = 0; i < events.length(); i++) {
						JSONObject o = events.getJSONObject(i);
						long id = o.getLong("id");
						JSONObject event = o.getJSONObject("event");
						if (id > lastEventId)
							lastEventId = id;
						// treat the event here...
						if (event.has("_type")) {
							if ("over".equals(event.getString("_type"))) {
								running = false;
								JOptionPane.showMessageDialog(null,
									    "The game is over!",
									    "Game over!",
									    JOptionPane.INFORMATION_MESSAGE);
							}
						} else {
							// Treat the event
							int p = event.getInt("player");
							int cell = event.getInt("cell");
							if (grid != null) {
								grid[cell] = Integer.toString(p);
								drawGrid();
							}
						}
						// but in this game, always just refresh the session
					}
				} catch (UnirestException e) {
					running = false;
					e.printStackTrace();
				}
			}
		}).start();
	}
}
