import { ActionFormData, ModalFormData, MessageFormData } from "@minecraft/server-ui";
import { world, system } from "@minecraft/server";
import * as utils from "../utils";
import * as inventory_utils from "../inventory_utils";
import * as Vector3 from "../vector3";
import * as gld from "../gld";
import * as wallet from "../wallet";
import { showApp as main_menu, checkDepletedBattery } from "./main_menu";
import { showApp as finances } from "./bank"; 

// App forms
let FormWarpUtility = undefined;
let FormWarpDetails = undefined;

const TELEPORT_COST = 10;
const SET_WARP_COST = 30;

const dimensionInfo = { "minecraft:overworld" : { color: "§l§2", texture: "textures/goe/spa/ui/warp_app" },
						"minecraft:nether" : { color: "§l§4", texture: "textures/goe/spa/ui/warp_app" },
						"minecraft:the_end" : { color: "§l§d", texture: "textures/goe/spa/ui/warp_app" },
						"empty_warp_slot" : { color: "§l§8", texture: "textures/goe/spa/ui/warp_set" },
						"default" : { color: "§l§8", texture: "textures/goe/spa/ui/warp" }
}

const warpData = gld.getAppData("warp");

export async function showApp(player){
    if (await checkDepletedBattery(player))
        return;
	
    let warpData = gld.getAppData("warp");

	FormWarpUtility = new ActionFormData().title(`${warpData.name}`)
		.body(
			gld.getScreenTitle(player) +
			`You can set warp locations, rename them, and teleport to them from this menu. \n` +
			`Note: Using this app costs §6${gld.coinSymbol}§f.\n\n` + 
			`Warps:\n`
		);
	
	FormWarpUtility.buttonsTargetForms = [];
	
	for (let i=1; i<=5; i++)
	{
		let warpTarget = `goe_spa_warp_${i}`;
		let warpName = "§b" + await player.getDynamicProperty(`${warpTarget}_name`);
		let warpDim = await player.getDynamicProperty(`${warpTarget}_dim`);
		
		
		let defaultName = "Warp "+i;
		if (warpName === undefined)
		{
			await player.setDynamicProperty(`${warpTarget}_name`, defaultName);
		}
		
		if (warpDim === undefined)
		{
			warpDim = "empty_warp_slot";

			let setWarpColor = wallet.canAfford(player, SET_WARP_COST) ? "§l§a" : "§l§c";
			warpName = `§l§bSet ${defaultName} here!\n${setWarpColor}Cost: ${SET_WARP_COST}⎊`;
		}
		
		let colorPrefix = dimensionInfo[warpDim].color;
		let button_texture = dimensionInfo[warpDim].texture;
		FormWarpUtility = FormWarpUtility.button(colorPrefix+warpName, button_texture);
	}
	FormWarpUtility = FormWarpUtility.button("Back", "textures/goe/spa/ui/back");
	
	FormWarpUtility.show(player).then((response) => {
		inventory_utils.replacePhoneIfUIClosed(player, response);
		let playerPressed = response.selection;
		if (playerPressed === undefined)
			return;
		
		if (playerPressed == 5)
		{
			player.playSound("goe_spa:button_click");
			main_menu(player);
		}
		else
		{
			let warpIndex = playerPressed+1;
			let warpTarget = `goe_spa_warp_${warpIndex}`;
			showWarpDetails(player, warpTarget, warpIndex);
		}
	});
}

export async function showWarpDetails(player, warpTarget, warpIndex)
{
	player.setDynamicProperty(`goe_spa_warp_target`, warpTarget);
	let warpName = await player.getDynamicProperty(`${warpTarget}_name`);
	let warpDim = await player.getDynamicProperty(`${warpTarget}_dim`);
	if (warpDim === undefined)
	{
		// Charge coins
		const canAfford = await wallet.canAfford(player, SET_WARP_COST);
		if (!canAfford) {
			player.playSound("goe_spa:reject");
			if (warpName === undefined)
				warpName = "Set Warp "+ warpIndex;

			showCantAffordForm(player, warpName, SET_WARP_COST);
			return;
		}

		// wallet.charge(player, SET_WARP_COST);

		player.playSound("goe_spa:button_click");

		await showSetWarp(player, warpTarget, warpIndex);
		return;
	}

	player.playSound("goe_spa:button_click");
	
	let formattedDim = warpDim.replace("minecraft:", "");
	formattedDim = utils.toTitleCase(formattedDim);

	let colorPrefix = dimensionInfo[warpDim].color;
	let button_texture = dimensionInfo[warpDim].texture;
	let location = await player.getDynamicProperty(`${warpTarget}_location`);
	
	let warpDetails = `${gld.getScreenTitle(player)}` + 
		`§5Dimension: §r${formattedDim}\n\n` +
		`§5Location: §e${location.x} ${location.y} ${location.z}\n\n`;

	let teleportColor = wallet.canAfford(player, TELEPORT_COST) ? "§l§a" : "§l§c";
	let setWarpColor = wallet.canAfford(player, SET_WARP_COST) ? "§l§a" : "§l§c";
	
	FormWarpDetails = new ActionFormData().title(warpData.name).body(warpDetails)
									.button(`§l§5Teleport\n${teleportColor}Cost: ${TELEPORT_COST}${gld.coinSymbol}`, "textures/goe/spa/ui/teleport_icon")
									.button(`§l§5Set Warp\n${setWarpColor}Cost: ${SET_WARP_COST}${gld.coinSymbol}`, "textures/goe/spa/ui/warp_set")
									.button("Back", "textures/goe/spa/ui/back");
	
	FormWarpDetails.show(player).then(async (response) => {
		inventory_utils.replacePhoneIfUIClosed(player, response);
		if (response.selection === undefined)
			return;

		let warpName = await player.getDynamicProperty(`${warpTarget}_name`);
		
		if (response.selection == 0) {
			// Charge coins
			const canAfford = await wallet.canAfford(player, TELEPORT_COST);
			if (!canAfford) {
				player.playSound("goe_spa:reject");
				showCantAffordForm(player, warpName, TELEPORT_COST);
				return;
			}

			teleportPlayer(player, warpTarget);

			wallet.charge(player, TELEPORT_COST, false);
		}
		else if (response.selection == 1) {
			// Charge coins
			const canAfford = await wallet.canAfford(player, SET_WARP_COST);
			if (!canAfford) {
				player.playSound("goe_spa:reject");
				showCantAffordForm(player, warpName, SET_WARP_COST);
				return;
			}

			showSetWarp(player, warpTarget);

			// wallet.charge(player, SET_WARP_COST);
		} else {
			showApp(player);
		}
		
	});
}

export async function showSetWarp(player, warpTarget, warpIndex)
{
	let currentWarpName = await player.getDynamicProperty(`${warpTarget}_name`);
	let warpUndefined = (currentWarpName === undefined);
	if (currentWarpName === undefined)
		currentWarpName = "Warp "+warpIndex;
	
	let location = Vector3.copyFloor(player.location);
	let warpRenameForm = new ModalFormData().title(warpData.name);
	warpRenameForm.textField(gld.getScreenTitle(player) + `§5Location: §e${location.x} ${location.y} ${location.z}`
	                        +"\n\n§5Warp name:§r\n(Max 15 characters)", currentWarpName, currentWarpName);

	warpRenameForm.show(player).then(formData => {
		inventory_utils.replacePhoneIfUIClosed(player, formData);
		let formDelay=10;
		if (formData.formValues)
		{
			let warpName = formData.formValues[0].substring(0,15);
			warpUndefined = false;
			player.setDynamicProperty(`${warpTarget}_name`, warpName);
			setWarpLocation(player, warpTarget);
			player.playSound("goe_spa:set_warp");
			system.runTimeout(() => { showApp(player); }, formDelay);
		}
		else
		{
			player.playSound("goe_spa:button_click");
			system.runTimeout(() => { showApp(player); }, formDelay);
		}
	});
}

export async function setWarpLocation(player, warpTarget)
{
	// Charge coins
	wallet.charge(player, SET_WARP_COST);

	let viewRotation = await player.getRotation().y;
	let newLocation = Vector3.copyFloor(player.location).toLocation();
	player.setDynamicProperty(`${warpTarget}_location`, newLocation);
	player.setDynamicProperty(`${warpTarget}_rotation`, viewRotation);
	player.setDynamicProperty(`${warpTarget}_dim`, player.dimension.id);
	//showWarpDetails(player, warpTarget);
}

export async function teleportPlayer(player, warpTarget) 
{
	inventory_utils.replacePhoneIfUIClosed(player);
	
	player.addTag("goe_spa_teleport_active");
	utils.runPlayerCommand(player, "inputpermission set @s movement disabled");
	
	player.dimension.spawnParticle("goe_spa:teleport", player.location);
	utils.playSound(player, "@a", "goe_spa:teleport");
	system.runTimeout(() => { teleportPlayerStep2(player, warpTarget); }, 25);
}
export async function teleportPlayerStep2(player, warpTarget)
{
	let warpLocation = await player.getDynamicProperty(`${warpTarget}_location`);
	let dim = await player.getDynamicProperty(`${warpTarget}_dim`);
	let colorPrefix = dimensionInfo[dim].color;
	let rotX = await player.getDynamicProperty(`${warpTarget}_rotation`);
	let name = await player.getDynamicProperty(`${warpTarget}_name`);
	let command = `tp @s ${warpLocation.x} ${warpLocation.y} ${warpLocation.z} ${rotX} 0`
	if (dim !== player.dimension.id)
		command = `execute in ${dim.replace("minecraft:","")} run tp @s ${warpLocation.x} ${warpLocation.y} ${warpLocation.z} ${rotX} 0`
	await utils.showPlayerInfoMessage(player, `Teleport to ${colorPrefix}${name}§r complete (§610 ${gld.coinSymbol}§r consumed)`);
	await utils.runPlayerCommand(player, command);
	await utils.runPlayerCommand(player, "inputpermission set @s movement enabled");
	await utils.runPlayerCommand(player, "particle goe_spa:teleport ~ ~ ~");
	await utils.playSound(player, "@a", "goe_spa:teleport");
	await player.removeTag("goe_spa_teleport_active");

	// wallet.charge(player, TELEPORT_COST);
}

async function showCantAffordForm(player, warpName, cost) {
    const CantAffordForm = new ActionFormData();
    CantAffordForm.title(warpData.name);
    CantAffordForm.body(
        gld.getScreenTitle(player) +
        `Not enough Smartcoins (§6${gld.coinSymbol}§r)\n\n` + 
        `  §9${warpName}§r\n\n` + 
        `§4Cost:      ${cost} ${gld.coinSymbol}§r\n` + 
        `§4Missing:   ${cost - wallet.getBalance(player)} ${gld.coinSymbol}§r\n\n`
    );
	CantAffordForm.button("§eGet Smartcoins", gld.getAppData("bank").icon);
    CantAffordForm.button("Back", "textures/goe/spa/ui/back");

    CantAffordForm.show(player).then((response) => {
        player.playSound("goe_spa:button_click");

		if (response.selection == 0) {
            finances(player);
            return;
        }

        showApp(player);
    });
}