
import * as audio from "./audio.js";
import SetConfig from "./set_config_class.js";
import $ from "./jquery.module.js";
import {langSwitch} from "./language.js";

let setConfigHandler = new SetConfig();
let config ;
let fail_message = "You did not have enough points to continue. <br/><img src='../../blocks/game_theme/theme/icons/tryagain.png' alt='try again'>"
function setConfig(config) {
	setConfigHandler.setConfig(config);
}


$(document).ready(async function() {

	setConfigHandler.then(async (configuration)=> {

		let config = {...configuration}; // Shallow copy because configuration is const, and we need to
		// add stuff.
		let width = screen.width;

		//Get a reference to the stage and output
		const stage = document.querySelector("#stage");
		const output = document.querySelector("#output");
		const endOfGame = document.querySelector("#endOfGame");
		let lastmove = 0;
		const victory_cell =2 ;
		let points = config.settings.points ;


		// background soundtrack ;


		let gameMessage;
		//The size of each cell
		let size = 60;

		const columns = 12;

		let keysPressed = {};
		//Arrow key codes
		const up = 38;
		const down = 40;
		const right = 39;
		const left = 37;
		const jump = 32; //space
		const shift = 16;
		const ctrl = 17;
		let map ;
		let map2 ;
		let cells = [];
		//Set the game background

		$("#stage").css('background-image', 'url(' + config.settings.background_img + ')');
		$("#layer1").css('background-image', 'url(' + config.settings.background_img + ')');

		if(config.settings.fail_message) {
			fail_message = config.settings.fail_message ;
		}

		/*
			IF THE USER HAS NOT SPECIFIED A MAP IN THE CONFIG FILE, THE MAPS BELOW WILL BE USED.
			IF THE USER DOES SPECIFY A MAP, THAT MAP WILL BE USED
		 */
		//The game map. These numbers align to different intro_images on the map;
		// use the map codes set up above
		// Keep the map as a 7x12 grid
		if (config.settings.map){
			map = config.settings.map ;
			console.log(map) ;
		}
		else {
			map = [
				[3, 4,4, 4, 8, 0, 4, 4, 0, 3,4,4],
				[4, 7, 7, 3, 0, 6, 7, 3, 4, 7,0,7],
				[0, 0, 6, 3, 0, 0, 0, 0, 4, 7,0,3],
				[3, 0, 7, 3, 3, 3, 0, 0, 7, 6,3,0],
				[0, 6, 7, 4, 3, 0, 6, 0, 0, 0,3,7],
				[3, 0, 6, 0, 0, 0, 3, 3, 3, 0,0,0],
				[0, 0, 0, 7, 5, 5, 5, 5, 5, 5,5,5]
			]
		}

		if (config.settings.map2){
			map2 = config.settings.map2 ;
			console.log(map2) ;
		}
		else {
			map2 = [ //the map that goes next
				[3, 4,3, 3, 2, 3, 3, 4, 3, 7,6,3],
				[4, 3, 3, 3, 0, 3, 3, 6, 3, 3,0,0],
				[0, 0, 6, 0, 0, 0, 0, 0, 0, 0,0,3],
				[0, 7, 3, 3, 6, 3, 3, 0, 3, 6,3,0],
				[3, 4, 3, 4, 3, 3, 3, 6, 0, 0,3,0],
				[3, 0, 3, 0, 6, 0, 0, 0, 3, 7,0,0],
				[7, 0, 0,0, 4, 3,0, 7, 0, 0,0,6]
			] ;
		}

		//The game objects map. Put the player where he should start.
		let gameObjects = [
			[0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0],
			[0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0],
			[0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0],
			[0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0],
			[0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0],
			[0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,1],
			[0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0]
		] ;
		const rows = map.length;
		//An automatic way of setting the Player's start position ;
		let playerRow;
		let playerColumn;

		// Check which directional buttons the user clicked
		let direction = "up";
		let playerDown = false;
		let playerUp = false;
		let playerLeft = false;
		let playerRight = false;

		for (let row = 0; row < rows; row++) {
			let thisCellRow = [];
			cells.push(thisCellRow);
			for (let column = 0; column < columns; column++) {
				if (gameObjects[row][column] === 1) {
					playerRow = row;
					playerColumn = column;
				}
				thisCellRow.push({});
			}
		}

		//Add a keyboard listener
		window.addEventListener("keydown", keydownHandler, false);
		window.addEventListener("keyup", keyupHandler, false);

		/**** SECTION TO HANDLE TOUCH DEVICES *****/
		// Note: we always show arrow buttons now
		// if ('ontouchstart' in window || navigator.maxTouchPoints) {
		// 	// User has a touch device
		// 	$("#arrow_div").removeClass('d-none');
		// }

		// THESE ARE THE KEYS FOR TOUCH DEVICES ;
		$('#up').on("click", async function () {
			if (playerRow > 0) {
				playerUp = true;
				//If it is,
				//Clear the Player's current cell
				gameObjects[playerRow][playerColumn] = 0;

				//Subtract 1 from the Player's row
				//to move it up one row on the map
				playerRow--;
				lastmove = 1;
				//Apply the Player's new updated position to the array
				gameObjects[playerRow][playerColumn] = 1;
			}
			await handleIt();
		});
		$('#down').on("click", async function () {
			if (playerRow < rows - 1) {
				playerDown = true;
				gameObjects[playerRow][playerColumn] = 0;
				playerRow++;
				lastmove = 2;
				gameObjects[playerRow][playerColumn] = 1;
			}
			await handleIt();
		});
		$('#left').on("click", async function () {
			if (playerColumn > 0) {
				playerLeft = true;
				gameObjects[playerRow][playerColumn] = 0;
				playerColumn--;
				lastmove = 3;
				gameObjects[playerRow][playerColumn] = 1;
			}
			await handleIt();
		});
		$('#right').on("click", async function () {
			if (playerColumn < columns - 1) {
				playerRight = true;
				gameObjects[playerRow][playerColumn] = 0;
				playerColumn++;
				gameObjects[playerRow][playerColumn] = 1;
				lastmove = 4;
			}
			await handleIt();
		});


		/***** END SECTION TO HANDLE TOUCH DEVICES ****/
		async function keydownHandler(event) {
			if (event.keyCode in keysPressed) return;
			keysPressed[event.keyCode] = event.type === 'keydown';
		}

		/**** Checks if the key press will stay within the game board (validPress).
		 Sets the value of the current cell to empty (=0)
		 Changes column or row, based on key pressed and then sets the value of new cell to player (=1)
		 Calls function to handle keypress
		 Resets the key pressed to none
		 ****/

		async function keyupHandler(event) {
			let validPress = false; // Variable to check if this move is within the game board
			if (keysPressed[up]) {
				//Find out if the Player's move will be within the playing field
				if (playerRow > 0) {
					playerUp = true;
					direction = "up";
					validPress = true;

					//If it is, clear the Player's current cell. 0 = empty cell ;
					gameObjects[playerRow][playerColumn] = 0;

					//Subtract 1 from the Player's row to move it up one row on the map
					playerRow--;
					lastmove = 1;

					//Apply the Player's new updated position to the array. 1= player value for cell image ;
					gameObjects[playerRow][playerColumn] = 1;
				}
			} else if (keysPressed[down]) {
				if (playerRow < rows - 1) {
					playerDown = true;
					direction = "down";
					validPress = true;
					gameObjects[playerRow][playerColumn] = 0;
					playerRow++;
					gameObjects[playerRow][playerColumn] = 1;
					lastmove = 2;
				}
			} else if (keysPressed[left]) {
				if (playerColumn > 0) {
					playerLeft = true;
					direction = "left";
					validPress = true;
					gameObjects[playerRow][playerColumn] = 0;
					playerColumn--;
					gameObjects[playerRow][playerColumn] = 1;
					lastmove = 3;
				}
			} else if (keysPressed[right]) {
				if (playerColumn < columns - 1) {
					playerRight = true;
					direction = "right";
					validPress = true;
					gameObjects[playerRow][playerColumn] = 0;
					playerColumn++;
					gameObjects[playerRow][playerColumn] = 1;
					lastmove = 4;
				}
			}

			//after handler reset keypress
			keysPressed = {};

			if (validPress) {
				await handleIt();
			}
		}

		async function handleIt() {
			let redraw = false;
			//Find what type of cell the player is in
			let cellType = map[playerRow][playerColumn];

			//Update health and points based on cell
			points += config.settings.cells[cellType].points;
			// Play that cells audio file

			audio.setAudioFile(config.settings.cells[cellType]?.audio) ;
			audio.playAudioFile(config.settings.cells[cellType]?.audio) ;

			// If the object is removable set the cell to empty
			if (config.settings.cells[cellType].removable) {
				map[playerRow][playerColumn] = 0
			}

			//Set the message for that cell
			let message = config.settings.cells[cellType].message;
			setMessage(message);

			//check for victory
			if (map[playerRow][playerColumn] ===  victory_cell) {
				endGame();
			}

			//check if the cell is a transition cell and change the map to the next one
			if (map[playerRow][playerColumn] ===  8 ) {
				gameObjects[playerRow][playerColumn] = 0;
				playerRow = 6 ;
				playerColumn = 3;
				gameObjects[playerRow][playerColumn] = 1;
				map = map2;
				redraw = true;
			}

			if (points <= 0) {
				endGame();
			} else {
				if (points <= 4) {
					setMessage("Points are getting low!");
				}

			}
			//Render the game-this actually draws everything again ;
			await render({redraw});
		}

		// THIS FUNCTION DRAWS THE GAME ;

		async function render({redraw}) {
			const shouldRedraw = typeof redraw !== "undefined" && redraw;
			//Clear the stage of img cells
			//from the previous turn
			if (shouldRedraw) {
				$(".grid-row").empty();
				$("#wait-for-next-map").removeClass("d-none");
			}

			//Render the game by looping through the map arrays
			for (let row = 0; row < rows; row++) {
				let gridRow = $("#row" + row.toString());
				for (let column = 0; column < columns; column++) {
					//current cell in _config map
					let cellNum = map[row][column];
					if (shouldRedraw) {
						// displayedCell?.cellDiv?.remove();
						cells[row][column] = {};
					}

					let displayedCell = cells[row][column];
					if ("cellImg" in displayedCell) {
						let cellImg = displayedCell.cellImg;
						let cell = cellImg[0];
						if (gameObjects[row][column] === 1) {
							cell.src = config.settings.cells[1].src;
							$(cell).addClass("player")
							// cell.setAttribute("class", "player");
						}
						else {
							if (cellImg.hasClass("player")) {
								cellImg.removeClass("player");
								cell.src = config.settings.cells[cellNum].src;
							}
						}
					} else {

						//Create a img tag called cell
						let cell = document.createElement("img");

						//Set its CSS class to "cell"
						cell.setAttribute("class", "cell");
						// let cell = $(`<img class="cell" alt="maze cell" />`);
						let cellDiv = $(`<div class="cell-div d-none"></div>`);
						cellDiv.append(cell);

						//Add the img tag to the <div id="stage"> tag
						gridRow.append(cellDiv);

						// Store displayed cell elements


						//Find the correct image for this map cell
						cell.src = config.settings.cells[cellNum].src;

						//Add the player from the config.settings.gameObjects array <-??
						if (gameObjects[row][column] === 1) {
							cell.src = config.settings.cells[1].src;
							$(cell).addClass("player")
							// cell.setAttribute("class", "player");
						}
						// $(".cell").css({top: row * size + "%", left: column * size + "%"});
						cellDiv.css({top: row * size, left: column * size, position: "absolute"});
						displayedCell.cellImg = $(cell);
						displayedCell.cellDiv = cellDiv;
					}
				}
			}
			let $cellDiv = $(".cell-div");
			// $(".cell-div").css("display", "inline-block");

			$cellDiv.css({
				display: "inline-block",
				width: config.settings.cellWidth,
				height: config.settings.cellHeight,
				padding: "5px",
				border: "1px solid black",
			});

			let $cell = $(".cell");
			for (let i = 0; i < $cell.length; i++) {
				let img = $cell[i];
				let $img = $(img);
				try {
					await img.decode();
				} catch(e) {
					console.log(`Got exception from decode on img ${$img.attr("src")}`)
					console.log(e);
				}
				let [width, height] = [img.naturalWidth, img.naturalHeight];
				if (width > height) {
					$img.css({
						width: config.settings.cellImageWidth,
						height: "auto"
					});
				}
				else {
					$img.css({
						width: "auto",
						height: config.settings.cellImageHeight
					});
				}
			}
			$cellDiv.removeClass("d-none");

			if (config.settings.cellImageBorder) {
				$(".cell").css("border", config.settings.cellImageBorder);
			}

			$("#wait-for-next-map").addClass("d-none");

			output.innerHTML = "Points: " + points;

		}

		// END THE GAME  ;
		function endGame() {
			$('#stage').remove();
			$("#message").remove();
			$("#arrow_div").remove();
			$("#output").remove();
			$("#instruction_help").hide();
			if (map[playerRow][playerColumn] === victory_cell) {
				$("#output").hide();

				$("#output2").html(config.options.successText).removeClass('d-none');
				audio.setAudioFile("../../audio/win_game.mp3") ;
				audio.playAudioFile("../../audio/win_game.mp3") ;

				setTimeout(function () {
					window.location.href = config.options.completionURL;
				}, 3000);
			} else if (points <= 0) {
				audio.setAudioFile("../../audio/lose_game.mp3") ;
				audio.playAudioFile("../../audio/lose_game.mp3") ;
				$("#output2").html(fail_message).removeClass('d-none');
				$("#death").show();
			}
		}



		function setMessage(_message) {
			$("#message").hide();
			if (points > 4) {
				$("#message").css('background-color', 'white');
			} else {
				$("#message").css('background-color', '#E18683');
			}
			$("#message").html(_message).show();
		}

		$("#output2").on("click", function () {
			location.reload();
		});
		const instructDiv = document.getElementById("instructions_help");
		instructDiv.innerHTML = config.options.instructionsPage1 ;
		for (const prop in config.settings.cells) {
			let bob ;
			const ul = document.createElement('ul');
			if (`${prop}` > 2  && `${prop}`< 8){
				bob = `${prop}`;
				const listItem = document.createElement('li');

				const img = document.createElement("img");
				img.src = config.settings.cells[bob].src ;

				listItem.innerHTML = config.settings.cells[bob].message ;
				listItem.prepend(img);
				ul.appendChild(listItem) ;
				instructDiv.appendChild(ul) ;
			}

		}

		//  FUNCTION TO START THE GAME BOARD  ;
		await render({redraw: true});

	});

	$("#play").on("click",function(){
		$(".instructions").addClass('d-none');
		$("#hint").removeClass('d-none');
		$("#message-div").append("<div id= 'message' class='p-3 game d-none ms-xxl-5 mt-2' ></div>")
		$("#message").text("This message will turn red when your points are running low.");
				$(".game").removeClass('d-none') ; // When instructions are ready move this to when clicked on play ;
		$("#new-arrow-div").removeClass('d-none');

	})
	$("#hint").on("click",function(){
		$(".instructions").removeClass('d-none');
		$(".game").addClass('d-none') ;
	})


});
export {setConfig};