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


let scoreboard = world.scoreboard;
export const overworld = world.getDimension('overworld');
export const nether = world.getDimension('nether');
export const the_end = world.getDimension('the_end');
export const dimensions = [overworld, nether, the_end];

export let player0 = undefined;


export function randomInt(min, max) {
	return Math.floor(Math.random() * (max - min + 1))+min;
}
export function floorVector(vector)
{
	return { x: Math.floor(vector.x), y: Math.floor(vector.y+0.5), z: Math.floor(vector.z) };
}

export async function waitForTicks(ticks, func) {
    return await system.runTimeout(func, ticks);
}


export async function waitForLoopEvent(ticks, callback) {
    return new Promise(resolve => {
        let id = 0;
        const event = async function () {
            var _a;
            if (await callback()) {
                resolve();
            }
            else {
                id = system.runTimeout(event, ticks);
            }
        };
        system.run(event);
    });
}

export async function onLoad() {
	if (player0)
		return;
	
	await waitForLoopEvent(1, () => {
		return world.getAllPlayers().length > 0;
	});
	player0 = await world.getAllPlayers()[0];
	if (!player0.hasTag("pu_sg_player0"))
		player0.addTag("pu_sg_player0");
}


export async function runCommand(command) {
	return await overworld.runCommandAsync(command);
}

export async function runPlayer0Command(command) {
	return await player0.runCommandAsync(command);
}

export async function runPlayerCommand(entity, command) {
	return await entity.runCommandAsync(command);
}
export async function runDelayedPlayerCommand(delay, entity, command) {
	return await system.runTimeout(() => { runPlayerCommand(entity, command); }, delay);
}
export async function runDelayedEntityCommand(delay, entity, command) {
	return await system.runTimeout(() => { runEntityCommand(entity, command); }, delay);
}
export async function runMobCommand(entity, command) {
	return await entity.runCommandAsync(command);
}
export async function runEntityCommand(entity, command) {
	return await entity.runCommandAsync(command);
}

export async function getEntities(entityType)
{
	const entities = await dimensions.flatMap((dim) => (dim.getEntities({ type: entityType })));
	return entities;
}
export async function getEntityInLocation(entityType, dim, centerLocation)
{
	const entities = await dim.getEntities( { type: entityType, location: centerLocation, closest: 1 } );
	return entities;
}
export async function getPlayerInLocation(dim, centerLocation)
{
	const players = await dim.getPlayers( { location: centerLocation, closest: 1 } );
	return players;
}
export async function getPlayersInRange(dim, centerLocation, minDist, maxDist)
{
	const players = await dim.getPlayers( { location: centerLocation, minDistance: minDist, maxDistance: maxDist } );
	return players;
}
export async function getEntitiesInRange(entityType, dim, centerLocation, minDist, maxDist)
{
	const entities = await dim.getEntities( { type: entityType, location: centerLocation, minDistance: minDist, maxDistance: maxDist } );
	return entities;
}

export async function countItemInInventory(player, itemTypeId)
{
	const inventory = player.getComponent("minecraft:inventory").container;
	let itemCount = 0;
	for (let i = 0; i < inventory.size; i++) {
		let item = inventory.getItem(i);
		if (item !== undefined && item.typeId === itemTypeId)
			itemCount += item.amount;
	}
	return itemCount
}
export async function showPlayerErrorMessage(player, message)
{
	await runPlayerCommand(player, "title @s actionbar "+message);
	await player.playSound("pu_sg:error", { volume: 0.8 } );
	//await runPlayerCommand(player, "playsound pu_sg:error @s ~ ~ ~ 1.00 1.00 1.00");
}

export async function tellraw(entity, target, msg) {
	return await entity.runCommandAsync(`tellraw ${target} {"rawtext":[{"text":"§r${msg}"}]}`);
}

export async function title(entity, target, msg) {
	return await entity.runCommandAsync(`titleraw ${target} title {"rawtext":[{"text":"§r${msg}"}]}`);
}
export async function subtitle(entity, target, msg) {
	return await entity.runCommandAsync(`titleraw ${target} subtitle {"rawtext":[{"text":"§r${msg}"}]}`);
}
export async function actionbar(entity, target, msg) {
	return await entity.runCommandAsync(`titleraw ${target} actionbar {"rawtext":[{"text":"§r${msg}"}]}`);
}

export async function playSound(entity, target, playSound, volume, pitch, minVolume) {
	let soundVolume = volume ? volume : 100;
	let soundPitch = pitch ? pitch : 1;
	let soundMinVolume = minVolume ? minVolume : 1;
	return await entity.runCommandAsync(`playsound ${playSound} ${target} ~ ~ ~ ${soundVolume} ${soundPitch} ${soundMinVolume}`);
}

export function concat2LinesWithPad(line1, line2)
{
	let len1 = line1.length;
	let len2 = line2.length;
	let message = "";
	if (len1 > len2) 
		message = line1 + "\n" + line2.padStart((len2+((len1-len2)/2)), " ");
	else if (len2 > len1)
		message = line1.padStart((len1+((len2-len1)/2)), " ") + "\n" + line2;
	else 
		message = line1 + "\n" + line2;
	return message;
}
export function debug(message) {
	return world.sendMessage(message);
}

export async function getBlockAtLocation(location)
{
	let block = await overworld.getBlock(location);
	if (block == null || block == undefined)
		return undefined;
	return block;
}

const ignoreBlocks = [
    { block: 'oak_log' },
    { block: 'spruce_log' },
    { block: 'birch_log' },
    { block: 'jungle_log' },
    { block: 'acacia_log' },
    { block: 'mangrove_log' },
    { block: 'cherry_log' },
    { block: 'dark_oak_log' },
    { block: 'leaves' },
    { block: 'leaves2' },
    { block: 'mangrove_leaves' },
    { block: 'cherry_leaves' },
    { block: 'azalea_leaves' },
    { block: 'vine' },
];


export async function isBlockSolid2(blockLocation)
{
	let block = await getBlockAtLocation(blockLocation);
	if (block == null || block == undefined || block.isAir == undefined || block.isAir == true)
		return false;
	
	if (ignoreBlocks.find((ignoreBlock) => { var _a; return (_a = block) === null || _a === void 0 ? void 0 : _a.permutation.matches(ignoreBlock.block, ignoreBlock.properties); }))
		return false;
	return true;
}

export const softerThanStoneBlockIds = [
	"minecraft:air",
    // Dirt & Soil
    "minecraft:dirt",
    "minecraft:coarse_dirt",
    "minecraft:grass_block",
    "minecraft:podzol",
    "minecraft:mycelium",
    "minecraft:rooted_dirt",

    // Sand & Gravel
    "minecraft:sand",
    "minecraft:red_sand",
    "minecraft:gravel",

    // Wood & Wood Variants
    "minecraft:oak_log",
    "minecraft:spruce_log",
    "minecraft:birch_log",
    "minecraft:jungle_log",
    "minecraft:acacia_log",
    "minecraft:dark_oak_log",
    "minecraft:mangrove_log",
    "minecraft:cherry_log",
    "minecraft:stripped_oak_log", // Add stripped versions if needed
    "minecraft:planks", // Add specific types if needed

    // Wool & Carpet
    "minecraft:wool", // All colors
    "minecraft:carpet", // All colors

    // Leaves
    "minecraft:oak_leaves",
    "minecraft:spruce_leaves",
    "minecraft:birch_leaves",
    "minecraft:jungle_leaves",
    "minecraft:acacia_leaves",
    "minecraft:dark_oak_leaves"
];

