import { system, world, ItemStack, Player } from "@minecraft/server";
import {
    colorCodeIds,
    entityBreak
} from "./spcrs_data";


// Messages
export function notificationMessage(message, player, removeAnouncer = false) {
    // const playerSetting = player.getDynamicProperty('oct_spcrs:disbale_delivery_notifications_setting');
    // if (playerSetting) return;

    const finalMessage = { rawtext: [] };
    const announcer = { "translate": "message.oct_spcrs.announcer", "with": ["\n"] };

    if (!removeAnouncer) {
        finalMessage.rawtext.push(announcer);
    }
    finalMessage.rawtext.push(message);

    player.sendMessage(finalMessage);
    player.playSound('random.levelup');

}


// Spawning Helper Functions
export function modifySpawnLocationFromBlockFace(spawnLocation, blockFace) {
    // Adjust the spawn location based on the clicked block face
    switch (blockFace) {
        case "Up":
            spawnLocation.y += 1;
            break;
        case "Down":
            spawnLocation.y -= 1;
            break;
        case "North":
            spawnLocation.z -= 1;
            break;
        case "South":
            spawnLocation.z += 1;
            break;
        case "West":
            spawnLocation.x -= 1;
            break;
        case "East":
            spawnLocation.x += 1;
            break;
        default:
            break;
    }

    // return the adjusted location
    return spawnLocation;
}
export function applyFacingRotation(source, spawnedEntity, spawnLocation, facingDirections) {
    // Calculate the angle in radians between the source and the spawn location
    const dx = source.location.x - spawnLocation.x;
    const dz = source.location.z - spawnLocation.z;
    let angle = Math.atan2(dz, dx);

    // Convert radians to normilized degrees and adjust for Minecraft's wanky axis
    let degrees = angle * (180 / Math.PI);
    degrees = (degrees - 90 + 360) % 360;

    // Calculate interval based on the number of directions
    let interval = 360 / facingDirections;

    // Snap to nearest interval based on facingDirections
    degrees = Math.round(degrees / interval) * interval;

    // Set the rotation
    spawnedEntity.setProperty('oct_spcrs:rotation', degrees);
}
export function applyFacingRotationNormal(source, spawnedEntity, spawnLocation, facingDirections, rotOffset = 0) {
    // Calculate the angle in radians between the source and the spawn location
    const dx = source.location.x - spawnLocation.x;
    const dz = source.location.z - spawnLocation.z;
    let angle = Math.atan2(dz, dx);

    // Convert radians to normilized degrees and adjust for Minecraft's wanky axis
    let degrees = angle * (180 / Math.PI);
    degrees = (degrees - 90 + 360) % 360;

    // Calculate interval based on the number of directions
    let interval = 360 / facingDirections;

    // Snap to nearest interval based on facingDirections
    degrees = Math.round(degrees / interval) * interval;

    // Set the rotation
    spawnedEntity.setRotation({ x: 0, y: degrees + rotOffset });
    // spawnedEntity.runCommand(`tp @s ~~~ ${degrees} 0`);
}
/**
 * Removes one item from the player's currently held item stack
 * @param {Player} player - The player to remove the item from
 */
export function removeHeldItem(player) {
    const inventory = player.getComponent("inventory").container;
    const currentStack = inventory.getItem(player.selectedSlotIndex);

    if (currentStack) {
        // Check the stack amount
        if (currentStack.amount > 1) {
            // Create a new item stack with one less item
            currentStack.amount -= 1;
            inventory.setItem(player.selectedSlotIndex, currentStack);
        } else {
            // If there's only one item left, remove it entirely
            inventory.setItem(player.selectedSlotIndex, undefined);
        }
    }

}


// Entity Helper functions
export function applyEntityColor(entity, colorCode) {
    // Ensure the color code exists in colorCodeIds
    if (colorCodeIds[colorCode] !== undefined) {
        // Apply the color
        if (entity.getProperty('oct_spcrs:car_color_id') !== undefined) {
            entity.setProperty('oct_spcrs:car_color_id', colorCodeIds[colorCode]);
            // console.error(`§2SUCCESS: Color changed to '${colorCode}'`);
        }
    } else {
        console.error(`§cERROR: '${colorCode}' is not a valid color code.`);
    }
}
/**
 * Spawns an item with an appended color code based on the entity's color property.
 * The entity must have the `oct_spcrs:car_color_id` property to determine the color code. 
 *
 * @param {Entity} entity - The entity whose color property is used to determine the color code.
 * @param {string} itemTypeIdWithoutColorCode - The base type ID of the item to spawn, without any color code.
 * @param {boolean} [encodeHP = false] - Optional flag to encode the entity's current health into the item.
 * @param {boolean} [encodeName = false] - Optional flag to encode the entity's name into the item.
 * @param {boolean} [encodeFuel = false] - Optional flag to encode the entity's current fuel into the item.
 *
 * **Example usage:**
 * - spawnColoredItem(entity, "oct_spcrs:car_1_", true, true);
 */
export function spawnColoredItem(entity, itemTypeIdWithoutColorCode, encodeHP = false, encodeName = false, encodeFuel = false) {
    // Retrieve the numeric color code from the mailbox entity
    const colorCodeId = entity.getProperty('oct_spcrs:car_color_id');

    // Map the numeric color code id to its corresponding key in colorCodeIds
    const colorCodeKey = Object.keys(colorCodeIds).find(key => colorCodeIds[key] === colorCodeId);

    // Check if the color code exists in colorCodeIds else spawn the fallback item
    const spawnItem = colorCodeKey ? `${itemTypeIdWithoutColorCode}${colorCodeKey}` : entityBreak[entity.typeId].fallbackSpawnItem;

    // Create the item
    const itemStack = new ItemStack(spawnItem, 1);

    // Encode the hp if passed
    if (encodeHP) {
        itemStack.setDynamicProperty('oct_spcrs:hp', entity.getComponent("health").currentValue);
    }

    // Encode the name if passed
    if (encodeName) {
        itemStack.setDynamicProperty('oct_spcrs:name', entity.nameTag);
    }

    // Encode the gas if passed
    if (encodeFuel) {
        itemStack.setDynamicProperty('oct_spcrs:fuel_level', entity.getDynamicProperty('oct_spcrs:fuel_level') ?? 0);
    }

    // Spawn the item
    entity.dimension.spawnItem(itemStack, entity.location);
}
/**
 * Empties the inventory of a given entity by spawning each item in the inventory
 * at the entity's current location (if it has any).
 * 
 * @param {Entity} entity - The entity whose inventory will be emptied.
 */
export function emptyInventoryItems(entity) {
    // Check if the entity has an inventory component
    if (!entity.hasComponent("inventory")) return;

    // Access the inventory container
    const inventory = entity.getComponent("inventory").container;

    // Iterate over each slot in the inventory and spawn the items at the entity's location
    for (let i = 0; i < inventory.size; i++) {
        const item = inventory.getItem(i);
        if (item) {
            // Spawn the item at the entity's location
            entity.dimension.spawnItem(item, entity.location);
        }
    }
}