class ServerEventsHandlers {
	constructor(game) {
		this.game = game;
	}

	version(data) {
		const servVersion = data[0];
		if(servVersion == REVISION) {
			return;
		}

		alert(strings["bad_version"]);
		this.game.conn.close();
		this.game.conn = null;
	}

	err(data) {
		alert(strings[data[0]]);
		this.game.conn.close();
		this.game.conn = null;
	}

	exploded(data) {
		const nickname = data[0];
		this.game.console("<span class=\"text-primary\">" + nickname + " drew a Detonating Cat!</span>");

		cardHUD("exploding", 1000);
	}

	// Legacy ??
	card_left(data) {
		$("#remaining-card-count").text(data[0]);
	}

	now_playing(data) {
		this.game.nowPlaying = data[0];
		this.game.console("<span class=\"text-info\">It is " + this.game.nowPlaying + "'s turn.</span>");

		this.game.drawPlayerList();

		// cmp with raw data because name isn't stored encoded
		if (data[0] == this.game.name) {
			this.game.ourTurn = true;
			this.game.assets["atomic.ogg"].play();
			document.title = strings["title_alert"];
			$(".bottom-notify-container").html(strings["your_turn"]);
		} else {
			this.game.ourTurn = false;
			document.title = strings["title_normal"]; // a bit fragile, needs to be same as <title>
			$(".bottom-notify-container").html("");
		}
	}

	players(data) {
		// Update players list
		this.game.players = data;
		this.game.spectators = this.game.spectators.filter(i => !this.game.players.includes(i));
		this.game.drawPlayerList();
		this.game.drawSpectatorsList();
	}

	spectators(data) {
		// Update spectators list
		this.game.spectators = data.filter(i => !this.game.players.includes(i));
		this.game.drawSpectatorsList();
	}

	joins(data) {
		const nickname = data[0];
		if(nickname == this.game.name && !this.game.started) {
			return this.game.start();
		}

		this.game.console("<span class=\"text-success\">" + nickname + " joined as a spectator.</span>");
		this.game.addSpectator(nickname);
	}

	upgrades(data) {
		const nickname = data[0];
		this.game.console("<span class=\"text-danger\">" + nickname + " is now spectating.</span>");
		this.game.removeSpectator(nickname);
	}

	downgrades(data) {
		const nickname = data[0];
		this.game.console("<span class=\"text-success\">" + nickname + " is now playing.</span>");
		this.game.addSpectator(nickname);
	}

	parts(data) {
		const nickname = data[0];
		this.game.console("<span class=\"text-danger\">" + nickname + " left the game.</span>");

		this.game.removeSpectator(nickname);
	}

	chat(data) {
		const nickname = data[0];
		const msg = data.join(" ").substring(nickname.length);
		this.game.console(`${nickname}: ${msg}`);
	}

	message(data) {
		// This refers to the 'message' container in the middle of the board
		// that can be used to display useful game info
		const msg = strings["message_" + data[0]];
		$("#message").html(msg);
		$("#message-container").removeClass("reveal");
	}

	clear_message(data) {
		$("#message").html("");
		$("#message-container").addClass("reveal");
	}

	bcast(data) {
		let msg = strings["bcast_" + data[0]];
		this.game.console(msg);
	}

	hand(data) {
		this.game.hand = data;
		$("#card-deck").empty();

		for (let i=0; i < this.game.hand.length; i++) {
			let card = $("<img class='card' src='assets/card_" + this.game.hand[i] + ".png' />");

			(function (gameState, cardNo, cardName) {
				card.on("click", function() {
					if (gameState.locked) {
						return;
					}

					if (gameState.favouring) {
						// Favour NOPE-logic is handled server-side :)
						gameState.send("a favour_what "+cardNo.toString());
						gameState.favouring = false;
						return;
					}

					if (gameState.combo > 1) {
						// Do we have enough cards?
						let cards = 0;
						for (var j=1; j < parts.length; j++) {
							if (parts[j] == cardName) {
								cards++;
								if (cards == gameState.combo) {
									break;
								}
							}
						}
						if (cards < gameState.combo) {
							gameState.console("You don't have enough " + strings["card_"+cardName] +
								" cards to do that!");
							return;
						}

						if (gameState.ourTurn) {
							gameState.send("play_multiple "+gameState.combo.toString()+" "+
								cardName);
							gameState.resetButtons();
							return;
						}
					}

					if ((gameState.ourTurn || cardName === "nope") && !cardName.startsWith("random")
							&& ( (!gameState.defusing && cardName !== "defuse")
							||    (gameState.defusing && cardName === "defuse") )) {
						gameState.send("play "+cardNo.toString());
						gameState.defusing = false;
					}
				});
			})(this.game, i, this.game.hand[i]);

			$("#card-deck").append(card);
		}
	}

	draw_pile(data) {
		const flag = data[0] == "yes" ? true : false;

		if(flag) {
			$("#draw-pile").html("<img class='card' src='assets/card_back.png' />");
			$("#draw-pile-counter").removeClass("reveal");
		} else {
			$("#draw-pile").html("");
			$("#draw-pile-counter").addClass("reveal");
		}
	}

	drew(data) {
		this.game.console("You drew <span class=\"text-warning\">" + strings["card_" + data[0]] + ".</span>");
		cardHUD(parts[1], 2000);
	}

	drew_other(data) {
		const nickname = data[0];
		this.game.console("<span class=\"text-primary\">" + nickname + " drew a card.</span>");

		// Animation
		$("#draw-pile-animation").html("<img src='assets/card_back.png' class='card' />");
		animate("#draw-pile-animation", "right", 125, -150, -15, "px");
	}

	wins(data) {
		const nickname = data[0];
		this.game.ourTurn = false;
		this.game.console("<span class=\"text-primary\"><b>" + nickname + " won!</b></span>");
		this.game.nowPlaying = "";
	}

	defusing(data) {
		this.game.console(strings["must_defuse"]);
		this.game.defusing = true;
	}

	played(data) {
		const [ nickname, card ] = data; 
		this.game.console(nickname + " played " + strings["card_" + card] + ".");
		
		$("#discard-pile").html("<img class='card' src='assets/card_" + card + ".png' />");

		if (card != "see3") {
			cardHUD(card, 1000);
		}
	}

	played_multiple(data) {
		const [nickname, x, card] = data;
		this.game.console(nickname + " played " + x + "x " + strings["card_" + card] + ".");

		$("#discard-pile").html("<img class='card' src='assets/card_" + card + ".png' />");

		if (x == 2) {
			cardHUD3([card, card], 1000);
		} else {
			cardHUD3([card, card, card], 1000);
		}
	}

	no_discard(data) {
		$("#discard-pile").html("");
	}

	q(data) {
		const type = data[0];
		if (type == "favour_what") {
			this.game.favouring = true;
			let perpetrator = data[1];
			this.game.console("<span class=\"text-primary\">" + perpetrator +
				" is asking you for a favour.</span>");
		} else if (type == "favour_who" || type == "random_who" || type == "steal_who") {
			(function (gameState) {
				modalChoice(function(player) {
					gameState.send("a " + type + " " + player);
				}, strings["question_" + type], gameState.players, entities(gameState.name), null);
			})(this.game);
		} else if (type == "steal_what") {
			(function (gameState) {
				modalChoice(function(card) {
					gameState.send("a " + type + " " + card);
				}, strings["question_" + type], cards, null, x => strings["card_" + x]);
			})(this.game);
		} else {
			ans = prompt(strings["question_" + type]);
			this.game.send("a " + type + " " + ans);
		}
	}

	q_cancel(data) {
		this.game.favouring = false;
	}

	seen(data) {
		cardHUD3(data, 2000);
		this.game.console("You saw " + strings["card_" + data[0]] + ", " + strings["card_" + data[1]] + " and " + 
			strings["card_" + data[2]] + ".");
	}

	favoured(data) {
		const [ perpetrator, victim ] = data;
		this.game.console(perpetrator + " is asking " + victim + " for a favour.");
	}

	favour_complete(data) {
		const [ perpetrator, victim ] = data;
		this.game.console(victim + " gave " + perpetrator + " a favour.");
	}

	favour_recv(data) {
		const remotePlayer = data[0];
		const card = strings["card_" + data[1]];
		this.game.console(remotePlayer + " gave you <span class=\"text-info\">" + card + "</span>.");
		cardHUD(data[1], 2000);
	}

	favour_gave(data) {
		const remotePlayer = data[0];
		const card = strings["card_" + data[1]];
		this.game.console("You gave " + remotePlayer + " <span class=\"text-info\">" + card + "</span>.");
	}

	randomed(data) {
		const [ perpetrator, victim ] = data;
		this.game.console(perpetrator + " took a random card from " + victim + ".");
	}

	random_n(data) {
		const [ perpetrator, victim ] = data;
		this.game.console(perpetrator + " asked " + victim + " for a random card, but they had nothing to give away!");
	}

	random_recv(data) {
		const remotePlayer = data[0];
		const card = strings["card_" + data[1]];

		this.game.console("You randomly took <span class=\"text-info\">" + card + "</span> from " + remotePlayer + ".");
		cardHUD(data[1], 2000);
	}

	random_gave(data) {
		const remotePlayer = data[0];
		const card = strings["card_" + data[1]];
		this.game.console(remotePlayer + " randomly took <span class=\"text-info\">" + card + "</span> from you.");
		cardHUD(data[1], 2000);
	}

	steal_n(data) {
		const [ perpetrator, victim, card ] = data;
		this.game.console(perpetrator + " asked " + victim + " for <span class=\"text-info\">"
				+ strings["card_" + card] + "</span>, but ended up empty-handed!");
	}

	steal_y(data) {
		const [ perpetrator, victim, card ] = data;
		this.game.console(perpetrator + " stole <span class=\"text-info\">" + 
				strings["card_" + card]+"</span> from " + victim + "!");
		cardHUD(card, 2000);
	}

	lock(data) {
		this.game.locked = true;
	}

	unlock(data) {
		this.game.locked = false;
	}
}