import { MinecraftDimensionTypes, Player, system, world } from "@minecraft/server";
import { ActionFormData, ModalFormData } from "@minecraft/server-ui";
import config from "nps_tbe/config";
import { Button, getRandomInt, getScoreboard } from "nps_tbe/others/my_API";
import { TutorialBook } from "./essentials";
world.beforeEvents.worldInitialize.subscribe(event => {
    TravelStone_0.initialize(event);
    TravelStone.initialize(event);
});
world.beforeEvents.playerBreakBlock.subscribe(event => {
    TravelStone.beforePlayerBreakBlock(event);
});
class TravelStone_0 {
    static initialize(event) { event.blockComponentRegistry.registerCustomComponent(this.componentName, new this()); }
    onTick(arg) {
        const nearbyPlayers = arg.dimension.getPlayers({ maxDistance: 32, location: arg.block.location });
        if (nearbyPlayers.length > 0) {
            arg.block.setType("nps_tbe:travel_stone_1");
            arg.dimension.spawnParticle("nps_tbe:travel_stone_0", arg.block.center());
        }
    }
    ;
}
TravelStone_0.componentName = "nps_tbe:1fbdf49b";
class TravelStoneButtons {
    static getAll() {
        return Object.values(this);
    }
    static getAllIconNames() {
        return this.getAll().map(button => button.rawtext);
    }
}
TravelStoneButtons.add = new Button("nps_tbe:travel_stone.add", "ui/icon_plus");
TravelStoneButtons.remove = new Button("nps_tbe:travel_stone.remove", "ui/icon_remove");
TravelStoneButtons.back = new Button("nps_tbe:travel_stone.back", "ui/icon_back");
TravelStoneButtons.travel = new Button("nps_tbe:travel_stone.travel", "ui/icon_travel");
TravelStoneButtons.wiki = new Button("nps_tbe:travel_stone.wiki", "ui/icon_question_mark");
TravelStoneButtons.cancel = new Button("nps_tbe:travel_stone.cancel", "ui/icon_cancel");
TravelStoneButtons.broken = new Button("nps_tbe:travel_stone.broken", "ui/icon_broken");
TravelStoneButtons.pin = new Button("nps_tbe:travel_stone.pin", "ui/icon_pin");
TravelStoneButtons.chest = new Button("nps_tbe:travel_stone.chest", "ui/icon_chest");
TravelStoneButtons.diamond = new Button("nps_tbe:travel_stone.diamond", "ui/icon_diamond");
TravelStoneButtons.star = new Button("nps_tbe:travel_stone.star", "ui/icon_star");
TravelStoneButtons.home = new Button("nps_tbe:travel_stone.home", "ui/icon_home");
TravelStoneButtons.emerald = new Button("nps_tbe:travel_stone.emerald", "ui/icon_emerald");
TravelStoneButtons.mountain = new Button("nps_tbe:travel_stone.mountain", "ui/icon_mountain");
TravelStoneButtons.palm_tree = new Button("nps_tbe:travel_stone.palm_tree", "ui/icon_palm_tree");
TravelStoneButtons.friends = new Button("nps_tbe:travel_stone.friends", "ui/icon_friends");
TravelStoneButtons.gps = new Button("nps_tbe:travel_stone.gps", "ui/icon_gps");
TravelStoneButtons.meat = new Button("nps_tbe:travel_stone.meat", "ui/icon_meat");
TravelStoneButtons.villager = new Button("nps_tbe:travel_stone.villager", "ui/icon_villager");
TravelStoneButtons.apple = new Button("nps_tbe:travel_stone.apple", "ui/icon_apple");
TravelStoneButtons.ruby = new Button("nps_tbe:travel_stone.ruby", "ui/icon_ruby");
TravelStoneButtons.carrot = new Button("nps_tbe:travel_stone.carrot", "ui/icon_carrot");
TravelStoneButtons.random = new Button("nps_tbe:travel_stone.random", "ui/icon_dice");
TravelStoneButtons.bell = new Button("nps_tbe:travel_stone.bell", "ui/icon_bell");
TravelStoneButtons.crafting = new Button("nps_tbe:travel_stone.crafting", "ui/icon_crafting_table");
TravelStoneButtons.iron_pickaxe = new Button("nps_tbe:travel_stone.iron_pickaxe", "ui/icon_iron_pickaxe");
TravelStoneButtons.wheat_field = new Button("nps_tbe:travel_stone.wheat_field", "ui/icon_wheat_field");
TravelStoneButtons.bookshelf = new Button("nps_tbe:travel_stone.bookshelf", "ui/icon_bookshelf");
TravelStoneButtons.map = new Button("nps_tbe:travel_stone.map", "ui/icon_map");
;
class TravelStone {
    static initialize(event) { event.blockComponentRegistry.registerCustomComponent(this.componentName, new this()); }
    static beforePlayerBreakBlock(event) {
        if (event.block.typeId !== "nps_tbe:travel_stone_2")
            return;
        TravelStone.markTravelStoneAsDestroyed(event.block);
    }
    onTick(arg) {
        arg.dimension.playSound('beacon.ambient', arg.block.location, {
            pitch: 0.7,
            volume: 1
        });
    }
    ;
    beforeOnPlayerPlace(arg) {
        TravelStone.unmarkTravelStoneAsDestroyed(arg.block);
    }
    ;
    onPlayerInteract(arg) {
        const player = arg.player;
        const travelStone = arg.block;
        const hasTag = TravelStone.playerHasTravelStoneTag(player, travelStone);
        if (hasTag) {
            // Si le joueur a déjà cette Travel Stone, afficher le menu de voyage
            TravelStone.openTravelStoneTravelOrWikiMenu(player, travelStone);
        }
        else {
            // Sinon, afficher le menu d'ajout ou Wiki
            TravelStone.openTravelStoneAddOrWikiForm(player, travelStone);
        }
    }
    static openTravelStoneTravelOrWikiMenu(player, travelStone) {
        const form = new ActionFormData();
        form.title({ translate: "nps_tbe:travel_stone.travel_or_wiki_title" });
        form.body({ translate: "nps_tbe:travel_stone.travel_or_wiki_body" });
        form.button(TravelStoneButtons.travel.rawtext, TravelStoneButtons.travel.iconPath);
        form.button(TravelStoneButtons.wiki.rawtext, TravelStoneButtons.wiki.iconPath);
        form.show(player).then(response => {
            if (response.canceled)
                return;
            if (response.selection === 0) {
                TravelStone.openTravelStoneTravelMenu(player, travelStone);
            }
            else if (response.selection === 1) {
                TravelStone.openTravelStoneWiki(player);
            }
        });
    }
    static openTravelStoneTravelMenu(player, travelStone) {
        const form = new ActionFormData();
        form.title({ translate: "nps_tbe:travel_stone.travel_menu_title" });
        form.body({ translate: "nps_tbe:travel_stone.travel_menu_body" });
        const travelStoneTags = this.filterTravelStoneTags(player.getTags());
        const currentTravelStoneTag = this.getTravelStoneTag(travelStone);
        const filteredTags = travelStoneTags.filter(tag => !tag.startsWith(currentTravelStoneTag));
        if (filteredTags.length === 0) {
            player.sendMessage({ translate: "nps_tbe:travel_stone.no_locations" });
            return;
        }
        const travelOptions = filteredTags.map(tag => {
            const [locationPart, dataPart] = tag.split(":").slice(1);
            const [dimensionIndex, x, y, z] = locationPart.split("_");
            const [iconIndex, ...nameParts] = dataPart.split("_");
            const isIntact = this.isTravelStoneIntact(world.getDimension(this.getDimensionIdFromIndex(parseInt(dimensionIndex))), { x: parseInt(x), y: parseInt(y), z: parseInt(z) });
            return {
                tag,
                name: isIntact ? { text: nameParts.join(" ") || "Unnamed" } : { translate: "nps_tbe:travel_stone.broken" },
                icon: isIntact ? TravelStone.travelStoneIcons[parseInt(iconIndex)] : TravelStoneButtons.broken,
                isIntact,
                dimensionIndex,
                x: parseInt(x),
                y: parseInt(y),
                z: parseInt(z)
            };
        });
        travelOptions.forEach(option => {
            const dimensionTranslationKey = `dimension.dimensionName${option.dimensionIndex}`;
            const text = {
                translate: "nps_tbe:gap_form_text",
                with: {
                    rawtext: [
                        option.name,
                        { text: '\n' },
                        { text: `(${option.x}, ${option.y}, ${option.z}, ` },
                        { translate: dimensionTranslationKey },
                        { text: ')' }
                    ]
                }
            };
            form.button(text, option.icon.iconPath);
        });
        form.show(player).then(response => {
            if (response.canceled)
                return;
            const selectedOption = travelOptions[response.selection];
            if (!selectedOption.isIntact) {
                // Ouvrir le menu pour supprimer une destination détruite
                TravelStone.openTravelStoneRemoveMenu(player, selectedOption.tag);
            }
            else {
                // Ouvrir le menu de confirmation pour voyager
                const destinationDimension = world.getDimension(this.getDimensionIdFromIndex(parseInt(selectedOption.dimensionIndex)));
                const destination = {
                    x: selectedOption.x,
                    y: selectedOption.y,
                    z: selectedOption.z
                };
                TravelStone.openTravelStoneConfirmMenu(player, this.getDimensionIdFromIndex(parseInt(selectedOption.dimensionIndex)), destination, destinationDimension, travelStone);
            }
        });
    }
    static openTravelStoneRemoveMenu(player, tag) {
        const form = new ActionFormData();
        form.title({ translate: "nps_tbe:travel_stone.remove_menu_title" });
        form.body({ translate: "nps_tbe:travel_stone.remove_menu_body" });
        form.button(TravelStoneButtons.remove.rawtext, TravelStoneButtons.remove.iconPath);
        form.show(player).then(response => {
            if (response.canceled)
                return;
            player.removeTag(tag);
            player.sendMessage({ translate: "nps_tbe:travel_stone.removed_message" });
        });
    }
    static isTravelStoneIntact(dimension, location) {
        const scoreboard = getScoreboard(config.travelStoneObjectiveId);
        const travelStoneTag = TravelStone.getTravelStoneTagFromLocation(dimension.id, location);
        return !scoreboard.hasParticipant(travelStoneTag);
    }
    static markTravelStoneAsDestroyed(travelStone) {
        const tag = this.getTravelStoneTag(travelStone);
        system.run(() => {
            const scoreboard = getScoreboard(config.travelStoneObjectiveId);
            scoreboard.setScore(tag, scoreboard.getParticipants().length);
        });
    }
    static unmarkTravelStoneAsDestroyed(travelStone) {
        const tag = this.getTravelStoneTag(travelStone);
        system.run(() => {
            const scoreboard = getScoreboard(config.travelStoneObjectiveId);
            if (scoreboard.hasParticipant(tag)) {
                scoreboard.removeParticipant(tag); // Supprime l'entrée associée au tag
            }
        });
    }
    static openTravelStoneConfirmMenu(player, dimensionId, destination, destinationDimension, travelStone) {
        const form = new ActionFormData();
        form.title({ translate: "nps_tbe:travel_stone.confirm_menu_title" });
        form.body({ translate: "nps_tbe:travel_stone.confirm_menu_body" });
        form.button({ translate: "nps_tbe:travel_stone.confirm_travel" }, TravelStoneButtons.travel.iconPath);
        form.show(player).then(response => {
            if (response.canceled) {
                player.sendMessage({ translate: "nps_tbe:travel_stone.travel_canceled" });
                return;
            }
            const entitiesToTeleport = player.dimension.getEntities({
                location: travelStone.location,
                maxDistance: 4,
            });
            player.sendMessage({ translate: "nps_tbe:travel_stone.tp_initiated" });
            const entityOriginalLocations = new Map();
            entitiesToTeleport.forEach(entity => {
                const flooredLocation = {
                    x: Math.floor(entity.location.x),
                    y: Math.floor(entity.location.y),
                    z: Math.floor(entity.location.z)
                };
                entityOriginalLocations.set(entity, flooredLocation);
                travelStone.dimension.spawnParticle("nps_tbe:invocation_column_0", entity.location);
            });
            travelStone.dimension.spawnParticle("nps_tbe:invocation_circle_0", travelStone.below().center());
            system.runTimeout(() => {
                const entitiesStillInRadius = [];
                const entitiesMoved = [];
                entitiesToTeleport.forEach(entity => {
                    const originalLocation = entityOriginalLocations.get(entity);
                    const currentLocation = {
                        x: entity.location.x,
                        y: entity.location.y,
                        z: entity.location.z
                    };
                    const hasMoved = originalLocation
                        && (Math.abs(originalLocation.x - currentLocation.x) > 1 || // Tolerance on x-axis
                            Math.abs(originalLocation.z - currentLocation.z) > 1 // Tolerance on z-axis
                        );
                    if (!hasMoved && TravelStone.isWithinRadius(travelStone.location, currentLocation, 4)) {
                        entitiesStillInRadius.push(entity);
                    }
                    else {
                        entitiesMoved.push(entity);
                    }
                });
                entitiesMoved.forEach(entity => {
                    if (entity instanceof Player) {
                        entity.sendMessage({ translate: "nps_tbe:travel_stone.tp_failed_moved" });
                    }
                });
                entitiesStillInRadius.forEach(entity => {
                    entity.dimension.spawnParticle('nps_tbe:tp_beam', entity.location);
                    const randomOffset = () => getRandomInt(-3, 3);
                    const randomDestination = {
                        x: destination.x + randomOffset(),
                        y: destination.y,
                        z: destination.z + randomOffset()
                    };
                    entity.teleport(randomDestination, { dimension: destinationDimension });
                    if (entity instanceof Player) {
                        const player = entity;
                        player.sendMessage({
                            translate: "nps_tbe:travel_stone.travel_success"
                        });
                    }
                });
                travelStone.dimension.spawnParticle("nps_tbe:tp_active", travelStone.below().center());
                system.runTimeout(() => {
                    try {
                        travelStone.dimension.spawnParticle("nps_tbe:invocation_circle_1", {
                            x: destination.x,
                            y: destination.y - 0.5,
                            z: destination.z
                        });
                        travelStone.dimension.playSound("nps_tbe:tp", destination);
                    }
                    catch { }
                }, 10);
            }, 100);
        });
    }
    static isWithinRadius(source, target, radius) {
        const dx = source.x - target.x;
        const dz = source.z - target.z;
        return dx * dx + dz * dz <= radius * radius;
    }
    static openTravelStoneAddOrWikiForm(player, travelStone) {
        const form = new ActionFormData();
        form.title({ translate: "nps_tbe:travel_stone.add_or_wiki_title" });
        form.body({ translate: "nps_tbe:travel_stone.add_or_wiki_body" });
        form.button(TravelStoneButtons.add.rawtext, TravelStoneButtons.add.iconPath);
        form.button(TravelStoneButtons.wiki.rawtext, TravelStoneButtons.wiki.iconPath);
        form.show(player).then((response) => {
            if (response.canceled)
                return;
            if (response.selection === 0) {
                // Ajout de la Travel Stone
                TravelStone.openTravelStoneAddForm(player, travelStone);
            }
            else if (response.selection === 1) {
                // Ouvrir le Wiki
                TravelStone.openTravelStoneWiki(player);
            }
        });
    }
    static openTravelStoneWiki(player) {
        TutorialBook.openTravelStoneForm(player);
    }
    static openTravelStoneAddForm(player, travelStone) {
        const form = new ModalFormData();
        form.title({ translate: "nps_tbe:travel_stone.title_add" });
        form.textField({ translate: "nps_tbe:travel_stone.enter_name" }, { translate: "nps_tbe:travel_stone.default_name" });
        const translatedIcons = TravelStone.travelStoneIcons.map(icon => ({ translate: icon.rawtext }));
        form.dropdown({ translate: "nps_tbe:travel_stone.choose_icon" }, translatedIcons);
        form.show(player).then(response => {
            if (response.canceled)
                return;
            const customName = response.formValues[0] || "Unnamed";
            const selectedIconIndex = response.formValues[1];
            // Sauvegarder les informations de la Travel Stone
            const travelStoneData = {
                name: customName,
                iconIndex: selectedIconIndex
            };
            // Appeler la méthode pour générer et ajouter le tag
            TravelStone.addTravelStoneTag(travelStone, player, travelStoneData);
            player.sendMessage({
                translate: "nps_tbe:travel_stone.added_message",
                with: [`${TravelStone.travelStoneIcons[selectedIconIndex]} ${customName}`]
            });
            travelStone.setType("nps_tbe:travel_stone_2");
            travelStone.dimension.spawnParticle("nps_tbe:travel_stone_1", travelStone.center());
        });
    }
    static filterTravelStoneTags(tags) {
        return tags.filter(tag => tag.startsWith("travelstone:"));
    }
    static getTravelStoneTag(travelStone) {
        const { dimension, location } = travelStone;
        const dimensionIndex = TravelStone.DimensionIndexes[dimension.id] ?? -1; // Utilise -1 si la dimension est inconnue
        return `travelstone:${dimensionIndex}_${Math.floor(location.x)}_${Math.floor(location.y)}_${Math.floor(location.z)}`;
    }
    static getTravelStoneTagFromLocation(dimensionId, location) {
        const dimensionIndex = TravelStone.DimensionIndexes[dimensionId] ?? -1; // Utilise -1 si la dimension est inconnue
        return `travelstone:${dimensionIndex}_${Math.floor(location.x)}_${Math.floor(location.y)}_${Math.floor(location.z)}`;
    }
    static getDimensionIdFromIndex(index) {
        const entry = Object.entries(TravelStone.DimensionIndexes).find(([_, idx]) => idx === index);
        return entry ? entry[0] : "unknown";
    }
    static addTravelStoneTag(travelStone, player, travelStoneData) {
        const { name, iconIndex } = travelStoneData;
        const { dimension, location } = travelStone;
        const dimensionIndex = TravelStone.DimensionIndexes[dimension.id] ?? -1;
        // Générer le tag en utilisant les informations nécessaires
        const tag = `travelstone:${dimensionIndex}_${Math.floor(location.x)}_${Math.floor(location.y)}_${Math.floor(location.z)}:${iconIndex}_${name}`;
        // Ajouter le tag au joueur
        player.addTag(tag);
    }
    static playerHasTravelStoneTag(player, travelStone) {
        const baseTag = this.getTravelStoneTag(travelStone);
        const tags = player.getTags();
        return tags.some(tag => tag.startsWith(baseTag)); // Vérifie uniquement si un tag commence par baseTag
    }
}
TravelStone.componentName = "nps_tbe:a4085282";
TravelStone.DimensionIndexes = {
    [MinecraftDimensionTypes.overworld]: 0,
    [MinecraftDimensionTypes.nether]: 1,
    [MinecraftDimensionTypes.theEnd]: 2
};
TravelStone.travelStoneIcons = [
    TravelStoneButtons.pin,
    TravelStoneButtons.chest,
    TravelStoneButtons.diamond,
    TravelStoneButtons.star,
    TravelStoneButtons.home,
    TravelStoneButtons.emerald,
    TravelStoneButtons.mountain,
    TravelStoneButtons.palm_tree,
    TravelStoneButtons.friends,
    TravelStoneButtons.gps,
    TravelStoneButtons.meat,
    TravelStoneButtons.villager,
    TravelStoneButtons.apple,
    TravelStoneButtons.ruby,
    TravelStoneButtons.carrot,
    TravelStoneButtons.random,
    TravelStoneButtons.bell,
    TravelStoneButtons.crafting,
    TravelStoneButtons.iron_pickaxe,
    TravelStoneButtons.wheat_field,
    TravelStoneButtons.bookshelf,
    TravelStoneButtons.map
];
