import { world, system } from "@minecraft/server";
import * as game from "./game";
import * as Vector3 from "./vector3";
import * as base from "./base";


export async function onTick()
{
	let players = await world.getAllPlayers();
	for(let player of players) 
	{
		if (player === undefined)
			continue;
		let slowFall = player.getDynamicProperty("tcs_cba_slow_fall");
		let slowFallHeight = player.getDynamicProperty("tcs_cba_slow_fall_height");
		if (slowFall === undefined || slowFallHeight < player.location.y)
			continue;
		
		game.runPlayerCommand(player, `effect @s slow_falling 5 1 true`);
		player.setDynamicProperty("tcs_cba_slow_fall", undefined);
		player.setDynamicProperty("tcs_cba_slow_fall_height", undefined);
	}
}
export async function onItemUse(event)
{
	let baseItem = event.itemStack.typeId;
	if (base.getData(baseItem) === undefined)
		return;

	await preloadBase(event.source, baseItem);
}

export async function onScriptEventReceive(event) 
{
	if (event.message === "yes")
		await loadBase(event.sourceEntity);
	else if (event.message === "no")
		await cancelLoadBase(event.sourceEntity);
	else if (event.message === "rotate")
		await rotateLoadBase(event.sourceEntity);
}

function print(coord)
{
	return "("+coord.x+" "+coord.y+" "+coord.z+")";
}
export async function preloadBase(player, baseId)
{
	let baseData = base.getData(baseId);
	
	let playerLocation = Vector3.copyCenter(player.location);
	let rot = player.getRotation();
	let playerFacing = Vector3.rotationToFacing(rot);
	
	let loadArea = base.load[playerFacing];
	
	let areaIsClear = await game.verifyAir2(playerLocation.add(loadArea.NW), playerLocation.add(loadArea.SE));
	
	if (!areaIsClear)
	{
		await game.showPlayerErrorMessage(player, "§cNot enough space");
		return;
	}
	
	let sizeOffset = (baseData.size-1)/2 + 4;
	let newCenterLocation = Vector3.copyFloor(loadArea.border).multiply(sizeOffset).add(player.location);

	if (baseData.offset !== undefined)
	{
		let loadOffset = rotateOffset(baseData.offset, baseData.size, loadArea.degrees);

		let baseSizeOffset = { x: sizeOffset-4, y: 0, z: sizeOffset-4 };
		newCenterLocation = Vector3.copyFloor(player.location).subtract(loadOffset).add(baseSizeOffset);
		//game.debug(`player=(${print(player.location)} baseSizeOffset=${print(baseSizeOffset)} `);
		//game.debug(`structure=(${print(Vector3.copyFloor(player.location).subtract(loadOffset))} square=${print(newCenterLocation)} `);
		//game.debug(`loadOffset=(${loadOffset.x} ${loadOffset.y} ${loadOffset.z})`);

	}

	//game.debug(`facing=${playerFacing}sizeOffset=${sizeOffset} border=${print(loadArea.border)}`);
	//game.debug(`player=${print(player.location)} center=${print(newCenterLocation)}`);
	
	await game.runPlayerCommand(player, `clear @s ${baseId} 0 1`);
	
	await game.runPlayerCommand(player, `setblock ${newCenterLocation.toCommand()} air`);
	let  square = player.dimension.spawnEntity("tcs_cba:square", newCenterLocation);
	square.triggerEvent(baseId);
	
	let buildHereLocation = playerLocation.add(loadArea.text);
	buildHereLocation.y = playerLocation.y;
	let buildHere = player.dimension.spawnEntity("tcs_cba:build_here2", buildHereLocation);
	buildHere.triggerEvent(baseId);
	await buildHere.teleport( buildHereLocation, { facingLocation: loadArea.facing.add(buildHereLocation).toLocation()} );
	
	buildHere.setDynamicProperty("tcs_cba_base", baseId);
	buildHere.setDynamicProperty("tcs_cba_degrees", loadArea.degrees);
	buildHere.setDynamicProperty("tcs_cba_rotate", 0);
	buildHere.setDynamicProperty("tcs_cba_square_location", newCenterLocation);
	
}
function rotateOffset(offset, buildSize, degrees)
{
	//game.debug(`offset=(${offset.x} ${offset.y} ${offset.z}) buildSize=${buildSize} degrees=${degrees}`);
	if (degrees == 90)
		return { x: buildSize - offset.z - 1, y: offset.y, z: offset.x };
	if (degrees == 180)
		return { x: buildSize - offset.x -1, y: offset.y, z: buildSize - offset.z -1 };
	if (degrees == 270)
		return { x: offset.z, y: offset.y, z: buildSize - offset.x - 1 };
	return offset;
}


async function cancelLoadBase(buildHere) {
	let baseId = await buildHere.getDynamicProperty("tcs_cba_base");
	let squareLocation = buildHere.getDynamicProperty("tcs_cba_square_location");
	if (squareLocation === undefined)
		squareLocation = buildHere.location;
	let square = await game.getEntityInLocation("tcs_cba:square", buildHere.dimension, squareLocation);
	await game.runMobCommand(buildHere, `give @p ${baseId}`);
	await clearBaseSummonMobs(buildHere, square);
}
async function rotateLoadBase(buildHere) {
	let rotate = buildHere.getDynamicProperty("tcs_cba_rotate") + 90;
	if (rotate === 360) rotate = 0;
	buildHere.setDynamicProperty("tcs_cba_rotate", rotate);
}

async function loadBase(buildHere)
{
	let baseId = await buildHere.getDynamicProperty("tcs_cba_base");
	let baseData = base.getData(baseId);
	
	let player = await game.getPlayerInLocation(buildHere.dimension, buildHere.location);
	player = player[0];
	
	if (baseData.fly === true)
	{
		player.setDynamicProperty("tcs_cba_slow_fall_height", player.location.y+15);
		game.runPlayerCommand(player, "inputpermission set @s movement disabled");
		game.runPlayerCommand(player, `effect @s levitation 3 20 true`);
		game.runPlayerCommand(player, `effect @s levitation 3 20 true`);
		game.runPlayerCommand(player, `effect @s resistance 10 255 true`);
		//game.runPlayerCommand(player, `effect @s slow_falling 15 1 true`);
		game.playSound(buildHere, "@s", "tcs_cba:fwooosh");
	}
	
	system.runTimeout(() => { loadBase2(buildHere, player); }, 10);
}
export async function loadBase2(buildHere, player)
{
	let squareLocation = buildHere.getDynamicProperty("tcs_cba_square_location");
	if (squareLocation === undefined)
		squareLocation = buildHere.location;
	let square = await game.getEntityInLocation("tcs_cba:square", buildHere.dimension, squareLocation);
	let baseId = buildHere.getDynamicProperty("tcs_cba_base");
	let baseDegrees = buildHere.getDynamicProperty("tcs_cba_degrees") + buildHere.getDynamicProperty("tcs_cba_rotate");
	if (baseDegrees >= 360)
		baseDegrees -= 360;
	
	let baseData = base.getData(baseId);
	let sizeOffset = (baseData.size-1)/2;
	

	// await game.runMobCommand(buildHere, `playsound tcs_cba:base_preparing @a[r=40] ~ ~ ~ 100 1 1`);
	square.dimension.playSound("tcs_cba:construction", square.location, {volume: 60});
	square.dimension.playSound("tcs_cba:placing_blocks", square.location, {volume: 60});
	square.dimension.spawnParticle("tcs_cba:construction", square.location);
	square.dimension.spawnParticle("tcs_cba:construction_spiral", square.location);
	let loadLocation = Vector3.copyFloor(square.location).add({x: -sizeOffset, y: 0, z: -sizeOffset});
	
	if(loadLocation.y < -64)
		loadLocation.y = -64;

	await game.runMobCommand(square, `structure load ${baseId} ${loadLocation.toCommand()} ${baseDegrees}_degrees none layer_by_layer 3`);

	await hideMobs(buildHere, square);
	
	system.runTimeout(() => { loadBase3(buildHere, square, baseId, player); }, 33);
}

export async function loadBase3(buildHere, square, baseId, player)
{
	let baseData = base.getData(baseId);
	let sizeOffset = (baseData.size-1)/2;
	let center = Vector3.copy(square.location);
	let loadLocation = center.add({x: -sizeOffset, y: 0, z: -sizeOffset});
	let baseDegrees = buildHere.getDynamicProperty("tcs_cba_degrees") + buildHere.getDynamicProperty("tcs_cba_rotate");
	if (baseDegrees >= 360)
		baseDegrees -= 360;

	if(loadLocation.y < -64)
		loadLocation.y = -64;

	await game.runPlayerCommand(player, `structure load ${baseId} ${loadLocation.toCommand()} ${baseDegrees}_degrees none`);
	system.runTimeout(() => { loadBase4(buildHere, square, baseId, player); }, 5);

	game.actionbar(player, "@a", `§r${baseData.name}§f created successfully.`);
	square.triggerEvent("tcs_cba:hide");
	game.runMobCommand(player, "inputpermission set @a[r=50] movement enabled");
	player.setDynamicProperty("tcs_cba_slow_fall", true);
}
export async function loadBase4(buildHere, square, baseId, player)
{
	let baseData = base.getData(baseId);
	let sizeOffset = (baseData.size+1)/2;
	let center = Vector3.copy(square.location);
	let loadLocation = center.add({x: -sizeOffset, y: 0, z: -sizeOffset});
	let otherCorner = center.add({x: sizeOffset, y: 0, z: sizeOffset});

	let clearCommand = `kill @e[type=item,x=${loadLocation.x},y=${loadLocation.y},z=${loadLocation.z},dx=${baseData.size},dy=${baseData.height},dz=${baseData.size}]`;
	game.runPlayerCommand(player, clearCommand);
	//let nearbyItems = await game.getEntitiesInArea("minecraft:item", player.dimension, loadLocation.toLocation(), otherCorner.toLocation(), "xz", undefined);
	//for (let item of nearbyItems)
	//	item.remove();

	clearBaseSummonMobs(buildHere, square);
	system.runTimeout(() => { loadBase5(player, clearCommand); }, 10);
}
export async function loadBase5(player, clearCommand)
{
	game.runPlayerCommand(player, clearCommand);
}



export async function hideMobs(buildHere, square) {
	let yesButton = await game.getEntityInLocation("tcs_cba:yes_button", buildHere.dimension, buildHere.location);
	let noButton = await game.getEntityInLocation("tcs_cba:no_button", buildHere.dimension, buildHere.location);
	let rotateButton = await game.getEntityInLocation("tcs_cba:rotate_button", buildHere.dimension, buildHere.location);
	buildHere.triggerEvent("tcs_cba:hide");
	yesButton.triggerEvent("tcs_cba:hide");
	noButton.triggerEvent("tcs_cba:hide");
	rotateButton.triggerEvent("tcs_cba:hide");
}
export async function clearBaseSummonMobs(buildHere, square) {
	let yesButton = await game.getEntityInLocation("tcs_cba:yes_button", buildHere.dimension, buildHere.location);
	let noButton = await game.getEntityInLocation("tcs_cba:no_button", buildHere.dimension, buildHere.location);
	let rotateButton = await game.getEntityInLocation("tcs_cba:rotate_button", buildHere.dimension, buildHere.location);
	square.remove();
	yesButton.remove();
	noButton.remove();
	rotateButton.remove();
	buildHere.remove();
}