import { Direction, EntityEquippableComponent, EntityInventoryComponent, EquipmentSlot, GameMode, ItemDurabilityComponent, ItemEnchantableComponent, StructureRotation, world } from "@minecraft/server";
import config from "nps_tbe/config";
export function getClosestPlayer(dimension, location) {
    const players = dimension.getPlayers({ closest: 1, location });
    return players[0];
}
export function getBoolean(player, key, fallback = true) {
    const value = player.getDynamicProperty(key);
    return typeof value === "boolean" ? value : fallback;
}
export function logAllDynamicProperties(player) {
    const properties = player.getDynamicPropertyIds();
    if (properties.length === 0) {
        console.warn(`[DynamicProperties] ${player.name} has no dynamic properties.`);
        return;
    }
    console.warn(`[DynamicProperties] ${player.name} :`);
    for (const key of properties) {
        const value = player.getDynamicProperty(key);
        console.warn(`- ${key}:`, value);
    }
}
export function getHorizontalDistance(a, b) {
    const dx = a.x - b.x;
    const dz = a.z - b.z;
    return Math.sqrt(dx * dx + dz * dz);
}
export function getScoreboard(objectiveId) {
    return world.scoreboard.getObjective(objectiveId) ?? world.scoreboard.addObjective(objectiveId, objectiveId);
}
export function getRelativeBlockInDirection(block, direction, cardinalDirection = getCardinalDirection(block)) {
    switch (cardinalDirection) {
        case Direction.South.toLocaleLowerCase(): {
            switch (direction) {
                case Direction.North: return block.south();
                case Direction.East: return block.west();
                case Direction.South: return block.north();
                case Direction.West: return block.east();
                case Direction.Up: return block.above();
                case Direction.Down: return block.below();
            }
        }
        case Direction.West.toLocaleLowerCase(): {
            switch (direction) {
                case Direction.North: return block.west();
                case Direction.East: return block.north();
                case Direction.South: return block.east();
                case Direction.West: return block.south();
                case Direction.Up: return block.above();
                case Direction.Down: return block.below();
            }
        }
        case Direction.North.toLocaleLowerCase(): {
            switch (direction) {
                case Direction.North: return block.north();
                case Direction.East: return block.east();
                case Direction.South: return block.south();
                case Direction.West: return block.west();
                case Direction.Up: return block.above();
                case Direction.Down: return block.below();
            }
        }
        case Direction.East.toLocaleLowerCase(): {
            switch (direction) {
                case Direction.North: return block.east();
                case Direction.East: return block.south();
                case Direction.South: return block.west();
                case Direction.West: return block.north();
                case Direction.Up: return block.above();
                case Direction.Down: return block.below();
            }
        }
    }
    return undefined; // Si la direction demandée n'est pas valide
}
export function hasEquippedElytra(player) {
    if (!player)
        return false;
    const equipment = getPlayerEquipment(player).getEquipment(EquipmentSlot.Chest);
    if (!equipment)
        return false;
    return equipment.typeId == "minecraft:elytra";
}
export function getUnbreakableVanillaBlocksIds() {
    return [
        "minecraft:bedrock",
        "minecraft:barrier",
        "minecraft:border_block",
        "minecraft:command_block",
        "minecraft:chain_command_block",
        "minecraft:repeating_command_block",
        "minecraft:structure_block",
        "minecraft:structure_void",
        "minecraft:end_portal_frame",
        "minecraft:end_portal",
        "minecraft:dragon_egg",
        "minecraft:deny",
        "minecraft:allow",
        "minecraft:end_gateway"
    ];
}
export function getWouldNotWantToBreak() {
    return [
        "minecraft:mob_spawner",
        "minecraft:vault",
        "minecraft:trial_spawner"
    ];
}
export function amountToDropWithFortune(fortuneLevel, initialDropAmount) {
    let totalAmount = initialDropAmount;
    let randomChance = Math.random();
    // Chances based on fortune level from the table provided
    const chances = {
        1: { double: 0.33, triple: 0, quadruple: 0 },
        2: { double: 0.25, triple: 0.25, quadruple: 0 },
        3: { double: 0.20, triple: 0.20, quadruple: 0.20 }
    };
    // Calculate bonus items based on fortune level
    if (fortuneLevel >= 1 && fortuneLevel <= 3) {
        const { double, triple, quadruple } = chances[fortuneLevel];
        if (randomChance < quadruple) {
            totalAmount *= 4; // quadruple includes the initial drop
        }
        else if (randomChance < quadruple + triple) {
            totalAmount *= 3; // triple includes the initial drop
        }
        else if (randomChance < quadruple + triple + double) {
            totalAmount *= 2; // double includes the initial drop
        }
    }
    else {
        totalAmount += getRandomInt(0, fortuneLevel);
    }
    return totalAmount;
}
export function getSilkTouchLevel(itemStack) {
    if (!itemStack) {
        return 0;
    }
    let silkTouchLevel = 0;
    let iec = itemStack.getComponent(ItemEnchantableComponent.componentId);
    if (iec.hasEnchantment("silk_touch")) {
        silkTouchLevel = iec.getEnchantment("silk_touch").level;
    }
    return silkTouchLevel;
}
export function getFortuneLevel(itemStack) {
    if (!itemStack) {
        return 0;
    }
    let fortuneLevel = 0;
    let iec = itemStack.getComponent(ItemEnchantableComponent.componentId);
    if (iec.hasEnchantment("fortune")) {
        fortuneLevel = iec.getEnchantment("fortune").level;
    }
    return fortuneLevel;
}
export function isLeaf(block) {
    if (!block)
        return;
    return block.getTags().includes("minecraft:leaf");
}
export function isLog(block) {
    if (!block)
        return;
    return block.getTags().includes("minecraft:log");
}
export function isHoe(itemStack) {
    if (!itemStack)
        return;
    return itemStack.getTags().includes("minecraft:is_hoe");
}
export function isPickaxe(itemStack) {
    if (!itemStack)
        return;
    return itemStack.getTags().includes("minecraft:is_pickaxe");
}
export function isHammer(itemStack) {
    if (!itemStack)
        return;
    return itemStack.getTags().includes("minecraft:is_hammer");
}
export function isShovel(itemStack) {
    if (!itemStack)
        return;
    return itemStack.getTags().includes("minecraft:is_shovel");
}
export function isAxe(itemStack) {
    if (!itemStack)
        return;
    return itemStack.getTags().includes("minecraft:is_axe");
}
export function isShears(itemStack) {
    return false;
}
export function getEnchantmentLevel(itemStack, enchantment) {
    if (!itemStack)
        return 0;
    let level = 0;
    let iec = itemStack.getComponent(ItemEnchantableComponent.componentId);
    if (iec == undefined) {
        return level;
    }
    if (iec.hasEnchantment(enchantment)) {
        level = iec.getEnchantment(enchantment).level;
    }
    return level;
}
export function containsKeyword(word, keywords) {
    if (!word || !keywords || keywords.length === 0)
        return false;
    return keywords.some(keyword => word.includes(keyword));
}
export function hasCommonTag(tagList1, tagList2) {
    if (!tagList1)
        return false;
    if (!tagList2)
        return false;
    return tagList2.some(tag => tagList1.includes(tag));
}
export function getRandomStructureRotation() {
    const structureRotations = [
        StructureRotation.None,
        StructureRotation.Rotate180,
        StructureRotation.Rotate270,
        StructureRotation.Rotate90
    ];
    return structureRotations[getRandomInt(0, structureRotations.length - 1)];
}
export function isInRange(value, min, max) {
    return value >= min && value <= max;
}
export function isMonster(entity) {
    return entity.matches({ families: ["mob", "monster"] });
}
export function isAnimal(entity) {
    return entity.matches({ excludeFamilies: ["monster"] }) && entity.matches({ families: ["mob"] });
}
export function rotateVectorByCardinalDirection(vector, cardinalDirection) {
    const [x, y, z] = vector;
    switch (cardinalDirection) {
        case Direction.North:
            return [x, y, z]; // Pas de rotation, le vecteur est orienté normalement
        case Direction.East:
            return [-z, y, x]; // Rotation de 90 degrés vers la droite
        case Direction.South:
            return [-x, y, -z]; // Rotation de 180 degrés
        case Direction.West:
            return [-z, y, -x]; // Rotation de 90 degrés vers la gauche
        default:
            throw new Error(`Invalid cardinal direction: ${cardinalDirection}`);
    }
}
export function giveItem(player, itemStack) {
    const playerInventory = getPlayerInventory(player);
    const result = playerInventory.container.addItem(itemStack);
    if (result == undefined)
        return;
    player.dimension.spawnItem(result, player.location);
}
export function damageItemStack(player, damage = 1) {
    if (damage <= 0) {
        return;
    }
    if (player.matches({ gameMode: GameMode.creative })) {
        return;
    }
    ;
    let playerEquipment = getPlayerEquipment(player);
    let mainhandItemStack = playerEquipment.getEquipment(EquipmentSlot.Mainhand);
    if (mainhandItemStack === undefined) {
        return;
    }
    let damageToApply = damage;
    let iec = mainhandItemStack.getComponent(ItemEnchantableComponent.componentId);
    if (iec) {
        let unbreakingLevel = 0;
        if (iec.hasEnchantment("unbreaking")) {
            unbreakingLevel = iec.getEnchantment("unbreaking").level;
        }
        const breakChance = 100 / (unbreakingLevel + 1);
        for (let i = 0; i < damage; i++) {
            const randomizeChance = Math.random() * 100;
            if (breakChance < randomizeChance) {
                damageToApply--;
            }
        }
    }
    let idc = mainhandItemStack.getComponent(ItemDurabilityComponent.componentId);
    if (idc.damage + damageToApply < idc.maxDurability) {
        idc.damage = idc.damage + damageToApply;
    }
    else {
        mainhandItemStack = undefined;
        player.playSound("random.break");
    }
    playerEquipment.setEquipment(EquipmentSlot.Mainhand, mainhandItemStack);
}
export function getItemStackDamage(itemStack) {
    const idc = itemStack.getComponent(ItemDurabilityComponent.componentId);
    return idc?.damage || 0;
}
export function getRandomInt(min, max) {
    min = Math.ceil(min);
    max = Math.floor(max);
    return Math.floor(Math.random() * (max - min + 1)) + min; // La valeur maximale est incluse et la valeur minimale est incluse 
}
export function decrementStack(player, decrement = 1) {
    if (player == undefined) {
        return;
    }
    if (player.matches({ gameMode: GameMode.creative })) {
        return;
    }
    const playerEquipment = getPlayerEquipment(player);
    const itemStack = playerEquipment.getEquipment(EquipmentSlot.Mainhand);
    if (itemStack.amount - decrement <= 0) {
        playerEquipment.setEquipment(EquipmentSlot.Mainhand, undefined);
    }
    else {
        itemStack.amount -= decrement;
        playerEquipment.setEquipment(EquipmentSlot.Mainhand, itemStack);
    }
}
export function getPlayerEquipment(player) {
    return player.getComponent(EntityEquippableComponent.componentId);
}
export function getBlockState(block, stateName) {
    return block.permutation.getState(stateName);
}
export function setBlockState(block, stateName, value) {
    const hasBlockState = getBlockState(block, stateName) != undefined;
    if (!hasBlockState) {
        return;
    }
    ;
    return block.setPermutation(block.permutation.withState(stateName, value));
}
export function getCardinalDirection(block) {
    return block.permutation.getState("minecraft:cardinal_direction");
}
export function setCardinalDirection(block, cardinalDirection) {
    setBlockState(block, "minecraft:cardinal_direction", cardinalDirection);
}
export function getRelativeDirection(cardinalDirection, direction) {
    switch (cardinalDirection) {
        case Direction.South: {
            return direction;
        }
        case Direction.East: {
            // Directions ajustées pour quand le bloc fait face à l'est
            switch (direction) {
                case Direction.North: return Direction.West;
                case Direction.East: return Direction.North;
                case Direction.South: return Direction.East;
                case Direction.West: return Direction.South;
            }
            break;
        }
        case Direction.North: {
            // Directions ajustées pour quand le bloc fait face au sud
            switch (direction) {
                case Direction.North: return Direction.South;
                case Direction.East: return Direction.West;
                case Direction.South: return Direction.North;
                case Direction.West: return Direction.East;
            }
            break;
        }
        case Direction.West: {
            // Directions ajustées pour quand le bloc fait face à l'ouest
            switch (direction) {
                case Direction.North: return Direction.East;
                case Direction.East: return Direction.South;
                case Direction.South: return Direction.West;
                case Direction.West: return Direction.North;
            }
            break;
        }
    }
    return undefined; // Si la direction demandée n'est pas valide
}
export function getRelativeBlock(block, cardinalDirection, direction) {
    switch (cardinalDirection) {
        case Direction.South: {
            // Directions absolues pour quand le bloc fait face au nord
            switch (direction) {
                case Direction.North: return block.south();
                case Direction.East: return block.west();
                case Direction.South: return block.north();
                case Direction.West: return block.east();
                case Direction.Up: return block.above();
                case Direction.Down: return block.below();
            }
            break;
        }
        case Direction.East: {
            // Directions ajustées pour quand le bloc fait face à l'est
            switch (direction) {
                case Direction.North: return block.west();
                case Direction.East: return block.north();
                case Direction.South: return block.east();
                case Direction.West: return block.south();
                case Direction.Up: return block.above();
                case Direction.Down: return block.below();
            }
            break;
        }
        case Direction.North: {
            // Directions ajustées pour quand le bloc fait face au sud
            switch (direction) {
                case Direction.North: return block.north();
                case Direction.East: return block.east();
                case Direction.South: return block.south();
                case Direction.West: return block.west();
                case Direction.Up: return block.above();
                case Direction.Down: return block.below();
            }
            break;
        }
        case Direction.West: {
            // Directions ajustées pour quand le bloc fait face à l'ouest
            switch (direction) {
                case Direction.North: return block.east();
                case Direction.East: return block.south();
                case Direction.South: return block.west();
                case Direction.West: return block.north();
                case Direction.Up: return block.above();
                case Direction.Down: return block.below();
            }
            break;
        }
    }
    return undefined; // Si la direction demandée n'est pas valide
}
export function incrementBlockState(block, stateName, increment, max) {
    const value = getBlockState(block, stateName);
    if (value == undefined) {
        return;
    }
    if ((value + increment) > max) {
        return;
    }
    setBlockState(block, stateName, value + increment);
}
export function getEnchantementLevel(itemStack, enchantement) {
    if (!itemStack) {
        return 0;
    }
    let enchantementLevel = 0;
    let iec = itemStack.getComponent(ItemEnchantableComponent.componentId);
    if (iec.hasEnchantment(enchantement)) {
        enchantementLevel = iec.getEnchantment(enchantement).level;
    }
    return enchantementLevel;
}
export function getPlayerInventory(player) {
    return player.getComponent(EntityInventoryComponent.componentId);
}
export class Button {
    constructor(rawtext, iconPath) {
        this.rawtext = rawtext;
        if (iconPath == undefined) {
            this.iconPath = undefined;
        }
        else {
            this.iconPath = config.texturePath + '/' + iconPath;
        }
    }
}
export class Buttons {
    static getAll() {
        return Object.values(this);
    }
    static getAllIconNames() {
        return this.getAll().map(button => button.rawtext);
    }
}
Buttons.access_anyway = new Button('nps_tbe:form_button.access_anyway', 'ui/icon_access_anyway');
Buttons.yes = new Button('nps_tbe:form_button.yes', 'ui/icon_accept');
Buttons.no = new Button('nps_tbe:form_button.no', 'ui/icon_close');
Buttons.back = new Button('nps_tbe:form_button.back', 'ui/icon_back');
Buttons.accept = new Button('nps_tbe:form_button.accept', 'ui/icon_accept');
Buttons.close = new Button('nps_tbe:form_button.close', 'ui/icon_close');
;
export function amountOf(itemType, player) {
    let amount = 0;
    const inventory = getPlayerInventory(player);
    // Vérifie les objets dans l'inventaire
    for (let i = 0; i < inventory.container.size; i++) {
        const itemStack = inventory.container.getItem(i);
        if (itemStack?.typeId === itemType)
            amount += itemStack.amount;
    }
    // Vérifie les objets dans l'équipement
    const equipment = getPlayerEquipment(player);
    [EquipmentSlot.Mainhand, EquipmentSlot.Offhand, EquipmentSlot.Head, EquipmentSlot.Chest, EquipmentSlot.Legs, EquipmentSlot.Feet]
        .forEach(slot => {
        if (equipment.getEquipment(slot)?.typeId === itemType)
            amount += equipment.getEquipment(slot).amount;
    });
    return amount;
}
export function applyItemDamage(player, itemStack, damage = 1) {
    // Skip damage calculation if the player is in creative mode
    if (player.matches({ gameMode: GameMode.creative }))
        return itemStack;
    if (!itemStack)
        return;
    let damageToApply = damage;
    // Check for Unbreaking enchantment
    const enchantmentComponent = itemStack.getComponent(ItemEnchantableComponent.componentId);
    if (enchantmentComponent) {
        const unbreaking = enchantmentComponent.getEnchantment("unbreaking");
        const unbreakingLevel = unbreaking ? unbreaking.level : 0;
        const breakChance = 100 / (unbreakingLevel + 1);
        // Adjust damage based on Unbreaking enchantment
        for (let i = 0; i < damage; i++) {
            if (Math.random() * 100 >= breakChance) {
                damageToApply--;
            }
        }
    }
    // Apply durability damage to the item
    const durabilityComponent = itemStack.getComponent(ItemDurabilityComponent.componentId);
    if (durabilityComponent) {
        if (durabilityComponent.damage + damageToApply < durabilityComponent.maxDurability) {
            durabilityComponent.damage += damageToApply;
        }
        else {
            return undefined; // Item breaks
        }
    }
    return itemStack;
}
export function getItemDurability(itemStack) {
    const durabilityComponent = itemStack.getComponent(ItemDurabilityComponent.componentId);
    if (durabilityComponent == undefined)
        return undefined;
    return durabilityComponent.maxDurability - durabilityComponent.damage;
}
