// Script that handles the guide book UIs
// Author: InnerTri



// Imports
// Important Global Variables
import {
    world
} from "@minecraft/server";

// guidebook chapters
import {
	chapters,
	disableableHorseStrings,
	getSettingsChapter
} from './chapters.js'






// display the guide book UI whenever a player right clicks with it
// giving of the book is done in tick.json
world.afterEvents.itemUse.subscribe(
	event => {
		if (event.itemStack.typeId === "cyn_hao:guide_book") {
			// console.warn(event.source.getDynamicProperty("cyn_hao:chapter"))
			displayForm(event.source);
		};
	}
);



// function to display "pages" of the guide "book"
// takes the player to display the ui form to as a parameter
// uses an imported array of all the chapters (as ActionFormData objects)
function displayForm(player) {
	
	// save the player's chapter for reference
	// (so we don't have to keep calling the getDynamicProperty function)
	let currentChapter = player.getDynamicProperty("cyn_hao:chapter");



	// if the player does not have a chapter set to display,
	// their chapter value is undefined (new player)
	// above chapters.length - 1 (since .length adds 1, there are chapters.length - 1 valid chapters. close book is not a chapter),
	// or below 0 (somehow)
	// set them to the home page
	// done per-player so multiple players can view different chapters at the same time
	if ((currentChapter == undefined) || (currentChapter < 0) || (currentChapter > (chapters.length - 1))) {
		player.setDynamicProperty("cyn_hao:chapter", 0);
		currentChapter = 0;
	}	



	// get the chapter this player is trying to view
	let form = chapters[currentChapter];



	// If the player is on the settings chapter,
	// we need to get some world dyn props, which obviously can't be done
	// if the chapter is created as a const.
	// so a function was made to get that data and return the form using it
	if (currentChapter == 29) {
		form = getSettingsChapter();
	}



	// display the form to the player
	// I could use switches and cases for this, but I didn't like the idea of nesting them
	// (That's probably hypocritical)
	form.show(player)
		.then(
		response => {

			// first, check if the player clicked to close the form
			// (or it is otherwise being told to close, e.g. the player is taking damage)
			// and if so, close the form
			// do NOT change this player's "cyn_hao:chapter" dyn property, 
			// so that the book will open back to the same page they were on
			if (response.canceled) {
				return;
			}



			// special cases for chapters that have more than just a back button
			switch (currentChapter) {
				// if the player is in chapter selection
				case 0:
					// there is an extra index, since the button at index chapters.length is the "Close Book" button 
					// which (obviously) does not have a chapter associated with it.
					if (response.selection === (chapters.length - 1)) {
						// make sure they retain the "chapter select" dyn property value
						player.setDynamicProperty("cyn_hao:chapter", 0);
						// close the book
						return;
					}

					// any other button is a dragon chapter they are trying to read
					else {
						// save the selection that the player clicked to their dyn property
						// offset by +1 since chapter index 0 is chapter selection
						player.setDynamicProperty("cyn_hao:chapter", response.selection + 1);
					}
				break;



				// if the player is in general info chapter
				case 1:
					// if they click the "duplicate book" button to duplicate the book
					if (response.selection === 0) {
						// summon another book at their feet via the same structure command our tick.json function uses
						// player.location.y + 1 in () because having the +1 in the following string to make ~ ~+1 ~
						// would result in a syntax error, with the problem being highlighed as the z coordinate
						// MAKE SURE THE STRUCTURE IS CORRECT!!! subfolder:structure_name
						// ought to make sure it's correct in the tick function as well,
						// otherwise new players won't get the book on joining!
						player.dimension.runCommand(`structure load "cynosia_horses:guide_book" ` + player.location.x + ` ` + (player.location.y + 1) + ` ` + player.location.z);
						player.dimension.runCommand(`tellraw @p[x=` + player.location.x + `, y=` + player.location.y + `, z=` + player.location.z + `] {"rawtext":[{"text":"§aHere you go!§r"}]}`);

						// close the book, saving their current chapter
						return;
					}
					// the only other thing they can click is the "back" button
					else {
						// so set their dyn property to be the chapter select
						// (a new form is opened lower in this code)
						player.setDynamicProperty("cyn_hao:chapter", 0);
					}
				break;



				// if the player is in the catalog chapter
				case 3:
					// if they click the "give catalog" button
					if (response.selection === 0) {
						// summon a catalog at their feet via a similar structure command our tick.json function uses
						// player.location.y + 1 in () because having the +1 in the following string to make ~ ~+1 ~
						// would result in a syntax error, with the problem being highlighed as the z coordinate
						// MAKE SURE THE STRUCTURE IS CORRECT!!! subfolder:structure_name

						// could probably use a spawnitem command here, but they wanted us to use strucute voids
						// for the initial book spawn for some reason instead of a script that spawns the item
						// so figured I might as well do that here too
						player.dimension.runCommand(`structure load "cynosia_horses:catalog_book" ` + player.location.x + ` ` + (player.location.y + 1) + ` ` + player.location.z);
						player.dimension.runCommand(`tellraw @p[x=` + player.location.x + `, y=` + player.location.y + `, z=` + player.location.z + `] {"rawtext":[{"text":"§aHere you go!§r"}]}`);

						// since they've done the one thing you can do here,
						// and players likely wouldn't want to get more catalogs,
						// set their chapter to chapter select
						player.setDynamicProperty("cyn_hao:chapter", 0);
						
						// close the book, saving their current chapter
						return;
					}
					// the only other thing they can click is the "go back" button
					else {
						// so set their dyn property to be the chapter select
						// (a new form is opened lower in this code)
						player.setDynamicProperty("cyn_hao:chapter", 0);
					}
				break;



				// if the player is in the settings chapter
				case 29:
					// handle the formValues array
					// the second value is for vanilla horse replacement
					let settingReplaceHorses = response.formValues[1]

					// if the value of the dyn prop has changed
					if (settingReplaceHorses !== world.getDynamicProperty("cyn_hao:replaceHorses")) {
						// set the value of the world's replace horses dyn prop
						// to be the newly-set value
						world.setDynamicProperty("cyn_hao:replaceHorses", settingReplaceHorses);
		
						// notify the world of this change
						// this might look backwards, but remember that this toggle
						// determines whether or not we REPLACE vanilla horses!
						// therefore, this means FALSE to REPLACE vanilla horses!
						if (settingReplaceHorses == false) {
							world.sendMessage("Vanilla Horses §awill spawn§r.");
						}
						else {
							world.sendMessage("Vanilla Horses §cwill not spawn§r.");
						}
					}



					// the next 19 values are for disabling specific horses
					// starting at 4 since index 0 is for vanilla horse replacement,
					// and values 1 - 4 are I guess null responses to the divider + labels? I guess?
					// not really sure why they even provide null responses, but easy enough to skip
					// -4 in the horse strings since form value 4 = horse string 1 due to those offsets
					// it's ugly and probably a little janky, but as always, "it works"
					let settingToggleIndexOffset = 5

					let j = 0;
					for (let i = settingToggleIndexOffset; i < response.formValues.length; i++) {

						// console.warn(`i: ${i} | response.formValues[i]: ${response.formValues[i]}`);
						// console.warn(`input ${"cyn_hao:disable" + disableableHorseStrings[j]} = ${response.formValues[i]}, world ${"cyn_hao:disable" + disableableHorseStrings[j]} = ${world.getDynamicProperty("cyn_hao:disable" + disableableHorseStrings[j])}`)
						if (response.formValues[i] !== world.getDynamicProperty("cyn_hao:disable" + disableableHorseStrings[j] + "")) {
							// set the value of the world's replace horses dyn prop
							// to be the newly-set value

							// console.warn(`Setting ${"cyn_hao:disable" + disableableHorseStrings[j]} to ${response.formValues[i]}`)
							world.setDynamicProperty("cyn_hao:disable" + disableableHorseStrings[j] + "", response.formValues[i]);
							console.info(`${disableableHorseStrings[j]} spawning: ${response.formValues[i]}`)
						}

						// console.warn("Disable " + disableableHorseStrings[i - 4] + ": " + response.formValues[i] + "")
						j++;
					}
		
					// after all settings have been addressed,
					// set the chapter to be chapter selection
					// since the only allowed button is the "submit" button
					// unfortunately we can't have a "back" button and a "submit" button
					player.setDynamicProperty("cyn_hao:chapter", 0);
				break;



				// next, if the player is NOT on the chapter selection screen, they are in a chapter
				// that is not special-cased here, so the only button they can click is the "back" button
				// this also covers the case that they have clicked something invalid
				default:

					// if the form is not being told to close,
					// check if their selection is (somehow) undefined
					if (response.selection === undefined) {
						// if it is, say that so we can debug it
						console.info("Player form selection undefined, setting to Chapter Select");
					}

					// if the player clicked the "back" button, or some sort of invalid button,
					// return to chapter select
					player.setDynamicProperty("cyn_hao:chapter", 0);
				break;
			}



			// if they were clicking to close the book, our code would have returned by now
			// therefore, they are trying to view another form,
			// so open a new form for the player
			// (no other parameters needed since the form references the dyn property)
			displayForm(player);
			return;

		}
	)
	.catch(
		error => {
			console.error(error, error.stack);
		}
	);

}