
<script lang="ts">
	import { onMount, onDestroy } from "svelte";
	import Header from '../../pieces/Header.svelte';
	import { fade, fly } from 'svelte/transition';


	import * as pong from "./client/pong";
	import { gameState } from "./client/ws";

	//user's stuff
	let user;
	let allUsers;

	//Game's stuff
	const options = new pong.InitOptions();
	const gameAreaId = "game_area";

	//boolean for html page
	let hiddenGame = true;
	let optionsAreNotSet = true;
	let showGameOptions = true;
	let showInvitations = false;
	let showError = false;
	let errorMessage = "";
	let showWaitPage = false;

	let invitations = [];

	let watchGameStateInterval;
	const watchGameStateIntervalRate = 142;

	onMount( async() => {
		user = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user`)
		.then( x => x.json() );
		allUsers = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user/all`)
		.then( x => x.json() );
		options.playerOneUsername = user.username;
	})

	onDestroy( async() => {
		clearInterval(watchGameStateInterval);
		pong.destroy();
	})

	function resetPage() {
		hiddenGame = true;
		optionsAreNotSet = true;
		showGameOptions = true;
		showInvitations = false;
		showError = false;
		showWaitPage = false;
		options.reset(user.username);
		pong.destroy();
	};

	const initGame = async() =>
	{
		optionsAreNotSet = false;
		showWaitPage = true;
		const matchOptions = pong.computeMatchOptions(options);
		try {
			const response = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/game/ticket`, {
				method : "POST",
				headers : {'Content-Type': 'application/json'},
				body : JSON.stringify({
					playerOneUsername : options.playerOneUsername,
					playerTwoUsername : options.playerTwoUsername,
					gameOptions : matchOptions,
					isGameIsWithInvitation : options.isSomeoneIsInvited
				})
			});
			console.log("status : " + response.status);
			const responseBody = await response.json();
			const token : string = responseBody.token;
			showWaitPage = false;
			if (response.ok && token)
			{
				watchGameStateInterval = setInterval(watchGameState, watchGameStateIntervalRate);
				pong.init(matchOptions, options, gameAreaId, token);
				hiddenGame = false;
			}
			else
			{
				console.log(responseBody);
				console.log("On refuse le ticket");
				errorMessage = responseBody.message;
				showError = true;
				options.reset(user.username);
				setTimeout(() => {
					optionsAreNotSet = true;
					showError = false;
					errorMessage = "";
				}, 5000);
			}
		} catch (e) {
			console.log(e);
		}
	}

	const initGameForInvitedPlayer = async(invitation : any) =>
	{
		optionsAreNotSet = false;
		showWaitPage = true;
		console.log("invitation : ");
		console.log(invitation);
		if (invitation.token)
		{
			watchGameStateInterval = setInterval(watchGameState, watchGameStateIntervalRate);
			options.playerOneUsername = invitation.playerOneUsername;
			options.playerTwoUsername = invitation.playerTwoUsername;
			options.isSomeoneIsInvited = true;
			options.isInvitedPerson = true;
			pong.init(invitation.gameOptions, options, gameAreaId, invitation.token);
			showWaitPage = false;
			hiddenGame = false;
		}
	}

	const watchGameState = () => {
		console.log("watchGameState");
		if (gameState) { // trigger Svelte reactivity
			gameState.matchStarted = gameState.matchStarted;
			gameState.matchEnded = gameState.matchEnded;
			gameState.matchAborted = gameState.matchAborted;
		}
		if (gameState.matchAborted || gameState.matchEnded)
		{
			clearInterval(watchGameStateInterval);
			console.log("watchGameState, end");
			setTimeout(() => {
				resetPage();
				console.log("watchGameState : setTimeout");
			}, 5000);
		}
	}

	const switchToGameOptions = () => {
		showGameOptions = true;
		showInvitations = false;
	}

	const fetchInvitations = async() => {
		showGameOptions = false;
		showInvitations = true;
		invitations = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/game/invitations`)
		.then(x => x.json());
	}

	const rejectInvitation = async(invitation) => {
		await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/game/decline`, {
			method: "POST",
			headers: { 'Content-Type': 'application/json'},
			body: JSON.stringify({
				token : invitation.token
			})
		})
		.then(x => x.json())
		.catch(error => console.log(error));
		fetchInvitations();
	}

	const acceptInvitation = async(invitation : any) =>
	{
		const res = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/game/accept`, {
			method: "POST",
			headers: { 'Content-Type': 'application/json'},
			body: JSON.stringify({
				token : invitation.token
			})
		}).catch(error => console.log(error));

		if (res && res.ok) {
			initGameForInvitedPlayer(invitation);
		}
	}

	function leaveMatch() {
		clearInterval(watchGameStateInterval);
		resetPage();
	};

</script>

<Header />
<!-- <div id="game_page"> Replacement for <body>.
	Might become useless after CSS rework. -->
<div id="game_page">

	{#if showError}
		<div class="div_game" in:fly="{{ y: 10, duration: 1000 }}">
			<fieldset>
				<legend>Error</legend>
				<p>{errorMessage}</p>
			</fieldset>
		</div>
	{/if}

	{#if !hiddenGame}
		{#if gameState.matchEnded}
			<div class="div_game" in:fly="{{ y: 10, duration: 1000 }}">
				<p>The match is finished !</p>
			</div>
		{:else if gameState.matchAborted}
			<div class="div_game" in:fly="{{ y: 10, duration: 1000 }}">
				<p>The match has been aborted</p>
			</div>
		{/if}
	{/if}

	<div id="canvas_container" hidden={hiddenGame}>
		<canvas id={gameAreaId}/>
	</div>

	{#if !hiddenGame}
		{#if gameState.matchStarted && !gameState.matchEnded}
			<div class="div_game">
				<button class="pong_button" on:click={leaveMatch}>forfeit</button>
			</div>
		{:else if !gameState.matchStarted}
			<div class="div_game">
				<button class="pong_button" on:click={leaveMatch}>leave matchmaking</button>
			</div>
		{/if}
	{/if}


	{#if showWaitPage}
		<div class="div_game" in:fly="{{ y: 10, duration: 1000 }}">
			<fieldset>
				<legend>Connecting to the game...</legend>
				<p>Please wait...</p>
			</fieldset>
		</div>
	{/if}

<!--  -->

	{#if optionsAreNotSet}
		{#if showGameOptions}
			<div id="game_option">
				<div class="div_game">
					<button class="pong_button" on:click={fetchInvitations}>Show invitations</button>
					<fieldset in:fly="{{ y: 10, duration: 1000 }}">
						<legend>game options</legend>
						<div>
							<input type="checkbox" id="multi_balls" name="multi_balls" bind:checked={options.multi_balls}>
							<label for="multi_balls">Multiples balls</label>
						</div>
						<div>
							<input type="checkbox" id="moving_walls" name="moving_walls" bind:checked={options.moving_walls}>
							<label for="moving_walls">Moving walls</label>
						</div>
						<div>
							<p>sound :</p>
							<input type="radio" id="sound_on" name="sound_selector" bind:group={options.sound} value="on">
							<label for="sound_on">on</label>
							<input type="radio" id="sound_off" name="sound_selector" bind:group={options.sound} value="off">
							<label for="sound_off">off</label>
						</div>
						<div>
							<input type="checkbox" id="isSomeoneIsInvited" bind:checked={options.isSomeoneIsInvited}>
							<label for="moving_walls">Invite a friend</label>
						</div>
						{#if options.isSomeoneIsInvited}
							<select bind:value={options.playerTwoUsername}>
								{#each allUsers as user }
									<option value={user.username}>{user.username}</option>
								{/each}
							</select>
						{/if}
						<div>
							<button class="pong_button" on:click={initGame}>PLAY</button>
						</div>
					</fieldset>
				</div>
			</div>
		{/if}

		{#if showInvitations}
			<div class="div_game">
				<button class="pong_button" on:click={switchToGameOptions}>Play a Game</button>
				<fieldset in:fly="{{ y: 10, duration: 1000 }}">
					<legend>invitations</legend>
					<button class="pong_button" on:click={fetchInvitations}>Reload</button>
					{#if invitations.length !== 0}
						{#each invitations as invitation}
							<div>
								{invitation.playerOneUsername} has invited you to play a pong !
								<button class="pong_button" on:click={() => acceptInvitation(invitation)}>V</button>
								<button class="pong_button" on:click={() => rejectInvitation(invitation)}>X</button>
							</div>
						{/each}
					{:else}
						<p>Currently, no one asked to play with you.</p>
					{/if}
				</fieldset>
			</div>
		{/if}
	{/if}

</div> <!-- div "game_page" -->

<style>
@font-face {
	font-family: "Bit5x3";
	src:
		url("/fonts/Bit5x3.woff2") format("woff2"),
		local("Bit5x3"),
		url("/fonts/Bit5x3.woff") format("woff");
	font-weight: normal;
	font-style: normal;
	font-display: swap;
}
#game_page {
	margin: 0;
	padding: 20px;
	background-color: #222425;
	position: relative;
	width: 100%;
	height: 100%;
}
#canvas_container {
	margin-top: 20px;
	text-align: center;
	/* border: dashed rgb(245, 245, 245) 5px; */
	/* max-height: 80vh; */
	/* overflow: hidden; */
}
canvas {
	/* background-color: #ff0000; */
	background-color: #333333;
	max-width: 75vw;
	/* max-height: 100vh; */
	width: 80%;
}

.div_game {
	text-align: center;
	font-family: "Bit5x3";
	color: rgb(245, 245, 245);
	font-size: x-large;
}
.div_game fieldset {
	max-width: 50vw;
	width: auto;
	margin: 0 auto;
}
.div_game fieldset div {
	padding: 10px;
}
.pong_button {
	font-family: "Bit5x3";
	color: rgb(245, 245, 245);
	background-color: #333333;
	font-size: x-large;
	padding: 10px;
}

</style>
