import { BlockPermutation, EntityEquippableComponent, EntityInventoryComponent, EquipmentSlot, GameMode, ItemDurabilityComponent, ItemEnchantableComponent, MinecraftDimensionTypes } from "@minecraft/server";
import config from "nps_mot/config";
export function shuffleArray(array) {
    // Copie du tableau pour ne pas modifier l'original
    const shuffledArray = [...array];
    // Algorithme de Fisher-Yates
    for (let i = shuffledArray.length - 1; i > 0; i--) {
        // Génère un index aléatoire entre 0 et i
        const j = Math.floor(Math.random() * (i + 1));
        // Échange les éléments à l'index i et j
        [shuffledArray[i], shuffledArray[j]] = [shuffledArray[j], shuffledArray[i]];
    }
    return shuffledArray;
}
export function getSilkTouchLevel(itemStack) {
    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) {
    let fortuneLevel = 0;
    let iec = itemStack.getComponent(ItemEnchantableComponent.componentId);
    if (iec.hasEnchantment("fortune")) {
        fortuneLevel = iec.getEnchantment("fortune").level;
    }
    return fortuneLevel;
}
export function replaceNonSpaceChars(input) {
    let modifiedInput = input.replace(/_/g, ' ');
    return modifiedInput.replace(/[^ ]/g, '?');
}
export function formatNumberWithHash(number) {
    return `#${number.toString().padStart(3, '0')}`;
}
export class HexEncoder {
    static encodeFalse(bits) {
        const count = Math.ceil(bits / 4);
        return '0'.repeat(count);
    }
    // Encode un nombre en chaîne hexadécimale (0 à 15)
    static encodeNibble(value) {
        return this.hexChars[value];
    }
    // Décode un caractère hexadécimal en un entier
    static decodeNibble(hexChar) {
        const value = this.hexChars.indexOf(hexChar.toUpperCase());
        if (value === -1) {
            throw new Error("Invalid hex character");
        }
        return value;
    }
    // Compte le nombre total de bits à 1 dans la chaîne hexadécimale
    static countSetBits(encodedString) {
        let count = 0;
        for (const char of encodedString) {
            const nibble = this.decodeNibble(char);
            count += this.countBitsInNibble(nibble);
        }
        return count;
    }
    // Compte le nombre de bits à 1 dans une valeur de 4 bits (nibble)
    static countBitsInNibble(value) {
        return value.toString(2).padStart(4, '0').split('').filter(bit => bit === '1').length;
    }
    // Définit un bit spécifique à 1 dans la chaîne hexadécimale
    static setBit(encodedString, index) {
        const hexIndex = Math.floor(index / 4);
        const bitIndex = index % 4;
        let hexChars = encodedString.split('');
        let nibble = this.decodeNibble(hexChars[hexIndex]);
        nibble |= (1 << bitIndex); // Définit le bit à 1
        hexChars[hexIndex] = this.encodeNibble(nibble);
        return hexChars.join('');
    }
    // Obtient la valeur d'un bit à un index spécifique
    static getBit(encodedString, index) {
        if (index < 0 || index >= 64) {
            throw new RangeError("Index out of bounds");
        }
        const hexIndex = Math.floor(index / 4);
        const bitIndex = index % 4;
        const nibble = this.decodeNibble(encodedString[hexIndex]);
        return (nibble & (1 << bitIndex)) !== 0;
    }
    static decodeToBinaryString(encodedString) {
        let binaryString = '';
        for (const char of encodedString) {
            const nibble = this.decodeNibble(char);
            binaryString += nibble.toString(2).padStart(4, '0'); // Convertir en binaire avec des zéros à gauche
        }
        return binaryString;
    }
}
HexEncoder.hexChars = "0123456789ABCDEF";
export function amountOf(itemType, player) {
    //returns the number of items in inventory
    let amount = 0;
    let inventory = getPlayerInventory(player);
    for (let i = 0; i < inventory.container.size; i++) {
        let itemStack = inventory.container.getItem(i);
        if (itemStack != undefined) {
            if (itemStack.typeId == itemType) {
                amount += itemStack.amount;
            }
        }
    }
    return amount;
}
export function isMonster(entity) {
    return entity.matches({ families: ["monster"] });
}
export class Effect {
    // Constructor
    constructor(id, duration = 15, amplifier = 0, hideParticles = true) {
        this.id = id;
        this.duration = duration;
        this.amplifier = amplifier;
        this.hideParticles = hideParticles;
    }
}
export function isHumanoidMonster(entity) {
    const humanoidMonster = [
        "minecraft:bogged",
        "minecraft:drowned",
        "minecraft:enderman",
        "minecraft:evocation_illager",
        "minecraft:husk",
        "minecraft:piglin_brute",
        "minecraft:pillager",
        "minecraft:skeleton",
        "minecraft:stray",
        "minecraft:vex",
        "minecraft:vindicator",
        "minecraft:warden",
        "minecraft:wither_skeleton",
        "minecraft:witch",
        "minecraft:zombie",
        "minecraft:zombie_pigman",
        "minecraft:zombie_villager"
    ];
    return humanoidMonster.includes(entity.typeId);
}
export function damageTool(player, damage = 1) {
    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 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 class Cube {
    constructor(origin, size) {
        this.origin = origin;
        this.size = size;
    }
}
export function getCardinalDirection(block) {
    let cardinalDirection = getBlockState(block, 'minecraft:cardinal_direction');
    return cardinalDirection;
}
export function getBlockState(block, stateName) {
    return block.permutation.getState(stateName);
}
export function setBlockState(block, stateName, value) {
    block.setPermutation(block.permutation.withState(stateName, value));
}
export function isInRange(value, min, max) {
    return value >= min && value <= max;
}
export function getFarmlandBlocks() {
    return [
        "minecraft:dirt",
        "minecraft:grass_block",
        "minecraft:grass",
        "minecraft:dirt_with_roots",
        "minecraft:grass_path"
    ];
}
export function getShovelableBlocks() {
    return [
        "minecraft:dirt",
        "minecraft:grass",
        "minecraft:grass_block",
        "minecraft:dirt_path",
        "minecraft:dirt_with_roots",
        "minecraft:snow_layer"
    ];
}
export function getWoodList() {
    return [
        "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:warped_stem",
        "minecraft:crimson_stem",
        "minecraft:bamboo_block"
    ];
}
export function validateBlockPlacementHeight(dimensionId, yStart) {
    switch (dimensionId) {
        case MinecraftDimensionTypes.overworld: {
            yStart = Math.max(-64, yStart);
            yStart = Math.min(320, yStart);
            return yStart;
        }
        case MinecraftDimensionTypes.nether: {
            yStart = Math.max(0, yStart);
            yStart = Math.min(128, yStart);
            return yStart;
        }
        case MinecraftDimensionTypes.theEnd: {
            yStart = Math.max(0, yStart);
            yStart = Math.min(256, yStart);
            return yStart;
        }
        default: {
            return undefined;
        }
    }
}
export function searchBlockId(block, blockIdList) {
    for (const blockId of blockIdList) {
        if (block.permutation.matches(blockId)) {
            return blockId;
        }
    }
    return undefined;
}
export function setblock(identifier, dimensionLocation) {
    dimensionLocation.dimension.getBlock({ x: dimensionLocation.x, y: dimensionLocation.y, z: dimensionLocation.z })?.setPermutation(BlockPermutation.resolve(identifier));
}
export function getPlayerEquipment(player) {
    return player.getComponent(EntityEquippableComponent.componentId);
}
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 getDimensionLocation(entity) {
    let dimensionLocation = {
        dimension: entity.dimension,
        x: entity.location.x,
        y: entity.location.y,
        z: entity.location.z
    };
    return dimensionLocation;
}
export function getPlayerInventory(player) {
    return player.getComponent(EntityInventoryComponent.componentId);
}
export function calculateEuclideanDistance(location1, location2) {
    let deltaX = location1.x - location2.x;
    let deltaY = location1.y - location2.y;
    let deltaZ = location1.z - location2.z;
    let distance = Math.sqrt(deltaX ** 2 + deltaY ** 2 + deltaZ ** 2);
    return distance;
}
export function getDimensionLocations(players) {
    const dimensionLocations = [];
    // Parcours des joueurs
    for (const player of players) {
        // Extraction de la dimension et des coordonnées de chaque joueur
        const { dimension, location } = player;
        // Troncature des coordonnées
        const truncatedLocation = {
            x: Math.floor(location.x),
            y: Math.floor(location.y),
            z: Math.floor(location.z)
        };
        // Création d'un objet DimensionLocation avec les valeurs tronquées
        const dimensionLocation = { dimension, ...truncatedLocation };
        // Ajout de l'objet créé au tableau dimensionLocations
        dimensionLocations.push(dimensionLocation);
    }
    return dimensionLocations;
}
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 class Button {
    constructor(rawtext, iconName) {
        if (rawtext !== undefined) {
            this.rawtext = 'nps_mot:form_button.' + rawtext;
        }
        else {
            this.rawtext = undefined;
        }
        if (iconName !== undefined) {
            this.iconPath = config.texturePath + '/ui/' + iconName;
        }
        else {
            this.iconPath = undefined;
        }
    }
}
export class Buttons {
}
Buttons.crafting_tables = new Button('crafting_tables', 'icon_crafting_tables');
Buttons.how_to_play = new Button('how_to_play', 'icon_question');
Buttons.ore_generation_distance = new Button('ore_generation_distance', undefined);
Buttons.ore_merchant_invocation = new Button('ore_merchant_invocation', 'icon_ore_merchant_invocation');
Buttons.update_1_1 = new Button(undefined, 'icon_update_1_1');
Buttons.update_1_2 = new Button(undefined, 'icon_update_1_2');
Buttons.codex = new Button('codex', 'icon_codex');
Buttons.yes = new Button('yes', 'icon_accept');
Buttons.no = new Button('no', 'icon_close');
Buttons.back = new Button('back', 'icon_back');
Buttons.accept = new Button('accept', 'icon_accept');
Buttons.close = new Button('close', 'icon_close');
Buttons.play = new Button('play', 'icon_tutorial');
Buttons.presentation = new Button('presentation', 'icon_tutorial');
Buttons.discord = new Button('join_discord', 'icon_discord');
Buttons.rate_us = new Button('rate_us', 'icon_rate');
Buttons.patch_notes = new Button('patch_notes', 'icon_patch_notes');
Buttons.bug_report = new Button('bug_report', 'icon_bug_report');
Buttons.apocalypse_0 = new Button('apocalyspe_0', 'icon_apocalyspe_0');
Buttons.apocalypse_1 = new Button('apocalyspe_1', 'icon_apocalyspe_1');
Buttons.apocalypse_2 = new Button('apocalyspe_2', 'icon_apocalyspe_2');
Buttons.apocalypse_3 = new Button('apocalyspe_3', 'icon_apocalyspe_3');
Buttons.apocalypse_4 = new Button('apocalyspe_4', 'icon_apocalyspe_4');
Buttons.ore_generation = new Button('ore_generation', 'icon_oreGeneration');
Buttons.armor_effects = new Button('armor_effects', 'icon_armorEffects');
Buttons.damage_indicators = new Button('damage_indicators', 'icon_damageIndicators');
Buttons.repair_kit_drops = new Button('repair_kit_drops', 'icon_repairKitDrops');
Buttons.jewel_drops = new Button('jewel_drops', 'icon_jewelDrops');
Buttons.monster_drops = new Button('monster_drops', 'icon_monsterDrops');
Buttons.apocalysis_difficulty = new Button('apocalysis_difficulty', 'icon_apocalysis_difficulty');
;
