package network.client;

import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;

import game.Player;
import network.Connexion;
import network.protocol.packets.ChangeCellPacket;
import network.protocol.packets.ConnexionInfoPacket;
import network.protocol.packets.DisconnectPacket;
import network.protocol.packets.EndGamePacket;
import network.protocol.packets.KeepAlivePacket;
import network.protocol.packets.LoginPacket;
import network.protocol.packets.PlayerJoinPacket;
import network.protocol.packets.PlayerLeavePacket;
import network.protocol.packets.StartGamePacket;
import network.protocol.packets.UpdatePlayerScorePacket;
import sudoku.io.SudokuSerializer;

public class ClientConnexion extends Connexion {

	private final Client client;

	public ClientConnexion(String address, short port, Client client) throws UnknownHostException, IOException {
		super(new Socket(address, port));
		this.client = client;
	}

	@Override
	public void close() {
		if (!this.isClosed()) {
			super.close();
			client.onDisconnect.emit();
		}
	}

	@Override
	public void visitPacket(ConnexionInfoPacket packet) {
		this.client.player = this.client.getGame().getPlayerById(packet.getConnectionId());
		client.onConnect.emit();
	}

	@Override
	public void visitPacket(KeepAlivePacket packet) {
		// we just send the packet back to the server
		sendPacket(packet);
	}

	@Override
	public void visitPacket(DisconnectPacket packet) {
		this.client.disconnectReason = packet.getReason();
		close();
	}

	@Override
	public void visitPacket(LoginPacket packet) {
		throw new UnsupportedOperationException("Unimplemented method 'visitPacketLogin'");
	}

	@Override
	public void visitPacket(PlayerJoinPacket packet) {
		this.client.addPlayer(packet.getPlayer());
		System.out.println("[Client] " + packet.getPlayer().getPseudo() + " joined the game !");
	}

	@Override
	public void visitPacket(PlayerLeavePacket packet) {
		this.client.getGame().removePlayer(packet.getPlayer());
	}

	@Override
	public void visitPacket(StartGamePacket packet) {
		this.client.getGame().startGame(SudokuSerializer.deserializeSudoku(packet.getSerializedSudoku()),
				packet.getInstant(), packet.getGameDuration());
		this.client.onGameStarted.emit();
	}

	@Override
	public void visitPacket(EndGamePacket packet) {
		Player winner = this.client.getGame().getLeaderboard().getFirst();
		this.client.getGame().stopGame();
		this.client.onGameEnd.emit(winner);
	}

	@Override
	public void visitPacket(UpdatePlayerScorePacket packet) {
		Player player = this.client.getGame().getPlayerById(packet.getPlayerId());
		assert (player != null);
		this.client.getGame().setPlayerRemainingCells(player, packet.getCellsLeft());
	}

	@Override
	public void visitPacket(ChangeCellPacket packet) {
		throw new UnsupportedOperationException("Unimplemented method 'visitPacketChangeCell'");
	}

}
