import { world, system } from "@minecraft/server";

//import * as forms from "../forms/item.js";
import * as putil from "../utils/player.js";

const overworld = world.getDimension("overworld");

var players = world.getPlayers();
var playersJoined = [];
var playersLeft = [];
var playersID = [];
var playerCount = players.length;
var playerRecent = "";

const actionItems = new Map([
	["minecraft:wooden_hoe", 0],
	["minecraft:stone_hoe", 1],
	["minecraft:iron_hoe", 2],
	["minecraft:golden_hoe", 3],
	["minecraft:diamond_hoe", 4],
	["minecraft:netherite_hoe", 5],
]);

// tick
system.runInterval(() => {

	//
	players = world.getPlayers();

	if (playerCount != players.length || playersJoined[playersJoined.length - 1] != playerRecent) {
		onPlayersUpdate(players);
	}

	playerCount = players.length;



	//
	overworld.runCommand("function world/tick");

	//
	for (let i = 0; i < players.length; i++) {
		let player = players[i];

		if (player.hasTag('action.leftClick')) {
			player.removeTag('action.leftClick');
			checkActionItems(player);
		}

		if (player.hasTag('form')) {
			player.removeTag('form');
			let tags = player.getTags();
			for (const tag of tags) {
				if (tag.startsWith("forms")) {
					player.removeTag(tag);

					const [, formInfo] = tag.split(/\s*:\s*/);
					if (formInfo) {
						const [formID, formB] = formInfo.split(".", 2).map((str) => parseInt(str));
						if (!isNaN(formID) && !isNaN(formB)) {
							world.sendMessage(`Valid: ${formID}, ${formB}`);
							putil.removeTagsWith(player, tags, `§xsys.wp-${formB}:`);
							if (formID == 1) {
								const { x: px, y: py, z: pz } = truncateVector3(player.location, 2);
								player.addTag(`§xsys.wp-${formB}: (${px}, ${py}, ${pz})`)
							}
						}
						else {
							world.sendMessage(`Invalid form data: ${formInfo}`);
						}
					}
					else {
						world.sendMessage(`Invalid form input: ${tag}`);
					}

				}
			}
		}

		let playerVariant = player.getComponent('minecraft:variant')?.value;

		if (playerVariant > 0) {
			waypointSelect(player, playerVariant);
			world.sendMessage("checking variant ---");
		}

	}

});

// second
system.runInterval(() => {

	//overworld.runCommand("function world/timer/second");   // crashing game for this particular function

}, 20);


function onPlayersUpdate(players) {

	let playersIDList = players.map(player => player.id);

	for (let i = 0; i < players.length; i++) {

		let player = players[i];
		let playerID = player.id;

		if (!playersJoined.includes(playerID)) {
			if (!playersLeft.includes(playerID)) {
				onPlayerJoin(player);
			}
			else {
				onPlayerRejoin(player);
			}
		}
	}

	for (let i = 0; i < playersJoined.length; i++) {

		let playerID = playersJoined[i];

		if (!playersIDList.includes(playerID)) {
			onPlayerLeave(playerID);
		}
	}

	world.sendMessage(`[System Update] joined: ${playersJoined}, left: ${playersLeft}`);

}
function onPlayerJoin(player) {

	playersJoined.push(player.id);

	playerRecent = player.id;

	if (!playersID.includes(player.id)) {
		playersID.push(player.id);
	}

	let playerLocation = truncateVector3(player.location, 2);

	world.sendMessage(`${player.name}(${player.id}) joined at ${JSON.stringify(playerLocation)} in ${putil.detGamemode(player)}!`);

}

function onPlayerLeave(playerID) {

	const index = playersJoined.indexOf(playerID);
	if (index != -1) {
		playersJoined.splice(index, 1);
	}

	if (playerID == playerRecent) {
		playerRecent = playersJoined[playersJoined.length - 1];
	}

	playersLeft.push(playerID);

	world.sendMessage(String(playerID + " left!"));
}
function onPlayerRejoin(player) {

	//
	const index = playersLeft.indexOf(player.id);
	if (index != -1) {
		playersLeft.splice(index, 1);
	}

	world.sendMessage(String(player.id + " rejoined!"));
	onPlayerJoin(player)
}



function checkActionItems(player) {
	for (const [item, id] of actionItems) {
		if (player.runCommand(`execute if entity @s[hasitem={item=${item},location=slot.weapon.mainhand}]`).successCount) {
			let tags = player.getTags();

			for (const tag of tags) {
				if (tag.startsWith(`§xsys.wp-${id}:`)) {

					const [, loc] = tag.split(/\s*:\s*/);
					if (loc) {
						const [x, y, z] = loc.replace(/[()]/g, "").split(",").map((str) => {
							const num = parseFloat(str);
							return isNaN(num) ? 0 : num;
                        });
                        world.sendMessage(`Location: ${x}, ${y}, ${z}`);
                        player.teleport({ x: x, y: y, z: z });
					}

					return;
				}
			}
			return;
		}
	}
}

function waypointSelect(player, id) {

	player.runCommand("event entity @s mythicus:npc.reset");

	const tags = player.getTags();

	for (const tag of tags) {
		if (tag.startsWith(`§xsys.wp-${id}:`)) {

			const [, loc] = tag.split(/\s*:\s*/);
			if (loc) {
				const [x, y, z] = loc.replace(/[()]/g, "").split(",").map((str) => {
					const num = parseFloat(str);
					return isNaN(num) ? 0 : num;
				});
				world.sendMessage(`Location: ${x}, ${y}, ${z}`);
				player.teleport({ x: x, y: y, z: z });
			}
			return;
		}
	}

	world.sendMessage(`Selected waypoint (${id}) does not exist.`);
}



function arrayRemove(array, value) {
	const index = array.indexOf(value);
	if (index !== -1) {
		array.splice(index, 1);
	}
	return array;
}
function truncateVector3(vector, places) {

	vector.x = parseFloat(vector.x.toFixed(places));
	vector.y = parseFloat(vector.y.toFixed(places));
	vector.z = parseFloat(vector.z.toFixed(places));

	return vector;

}