import { ItemStack, world, system, ItemLockMode } from "@minecraft/server";
/**
 * Handles dynamic hot bar items that change based on player's run state
 * Items are locked in specific slots and cannot be dropped or moved
 */
export class ItemHandler {
    timeTracker;
    timeTrackerUI;
    areaData;
    settingsManager;
    settingsUI;
    // Item identifiers
    ITEMS = {
        START_GAME: "mbl:start_game",
        SETTINGS: "mbl:settings",
        STATS: "mbl:stats",
        CHECKPOINT: "mbl:checkpoint",
        EXIT: "mbl:exit"
    };
    // Hot bar slot positions
    SLOTS = {
        SLOT_4: 4, // 5th slot
        SLOT_7: 7, // 8th slot
        SLOT_8: 8 // 9th slot
    };
    constructor(timeTracker, timeTrackerUI, areaData, settingsManager, settingsUI) {
        this.timeTracker = timeTracker;
        this.timeTrackerUI = timeTrackerUI;
        this.areaData = areaData;
        this.settingsManager = settingsManager;
        this.settingsUI = settingsUI;
        this.initializeEventHandlers();
    }
    /**
     * Initialize event handlers for item usage and inventory management
     */
    initializeEventHandlers() {
        // Handle item use (allow custom items only)
        world.afterEvents.itemUse.subscribe((event) => {
            this.handleItemUse(event.source, event.itemStack);
        });
        // === PROTECTION SYSTEM ===
        // Prevent block breaking
        world.beforeEvents.playerBreakBlock.subscribe((event) => {
            event.cancel = true;
        });
        // Prevent entity interaction (villagers, item frames, etc.)
        world.beforeEvents.playerInteractWithEntity.subscribe((event) => {
            event.cancel = true;
        });
        world.beforeEvents.playerInteractWithBlock.subscribe((event) => {
            event.cancel = true;
        });
        // Prevent item use on blocks (buttons, levers, doors, etc.)
        world.beforeEvents.itemUse.subscribe((event) => {
            const item = event.itemStack;
            // Only allow our custom game items
            if (!item || !this.isGameItem(item)) {
                event.cancel = true;
            }
        });
        // Prevent attacking/hurting entities
        world.beforeEvents.entityRemove.subscribe((event) => {
            const entity = event.removedEntity;
            // Prevent any entity removal by players (if possible to detect)
        });
        // Update items every tick to ensure they're always present
        system.runInterval(() => {
            for (const player of world.getAllPlayers()) {
                this.updatePlayerItems(player);
                // Clear inventory except for hot bar slots 0, 1, 2
                const container = player.getComponent("inventory")?.container;
                if (container) {
                    // Clear all slots except 4, 7, and 8
                    for (let i = 0; i < container.size; i++) {
                        if (i !== 4 && i !== 7 && i !== 8) {
                            const item = container.getItem(i);
                            if (item) {
                                container.setItem(i, undefined);
                            }
                        }
                    }
                }
            }
        }, 20); // Update every second
        // Give items on player spawn
        world.afterEvents.playerSpawn.subscribe((event) => {
            this.updatePlayerItems(event.player);
        });
    }
    /**
     * Check if an item is one of our game items
     */
    isGameItem(item) {
        const itemId = item.typeId;
        return Object.values(this.ITEMS).includes(itemId);
    }
    /**
     * Update player's hot bar items based on their run state
     */
    updatePlayerItems(player) {
        const container = player.getComponent("inventory")?.container;
        if (!container)
            return;
        const hasActiveRun = this.timeTracker.hasActiveRun(player.id);
        if (hasActiveRun) {
            // In run: Last Checkpoint (slot 4) - only if not disabled, Stats (slot 7), Exit Run (slot 8)
            const settings = this.settingsManager.getSettings(player);
            if (!settings.disableCheckpointItem) {
                this.setItem(container, this.SLOTS.SLOT_4, this.ITEMS.CHECKPOINT, "§6Last Checkpoint", [
                    "§7Teleport to your last checkpoint"
                ]);
            }
            else {
                container.setItem(this.SLOTS.SLOT_4, undefined);
            }
            this.setItem(container, this.SLOTS.SLOT_7, this.ITEMS.STATS, "§bStats", [
                "§7View your statistics"
            ]);
            this.setItem(container, this.SLOTS.SLOT_8, this.ITEMS.EXIT, "§cExit Run", [
                "§7End your current run",
                "§7and return to spawn"
            ]);
        }
        else {
            // Not in run: Start Game (slot 4), Stats (slot 7), Settings (slot 8)
            this.setItem(container, this.SLOTS.SLOT_4, this.ITEMS.START_GAME, "§aStart Game", [
                "§7Begin a new parkour run"
            ]);
            this.setItem(container, this.SLOTS.SLOT_7, this.ITEMS.STATS, "§bStats", [
                "§7View your statistics"
            ]);
            this.setItem(container, this.SLOTS.SLOT_8, this.ITEMS.SETTINGS, "§eSettings", [
                "§7Configure your preferences"
            ]);
        }
    }
    /**
     * Set an item in a specific slot with custom name and lore
     */
    setItem(container, slot, itemId, name, lore) {
        const existingItem = container.getItem(slot);
        // Check if item already exists with correct properties
        if (existingItem && existingItem.typeId === itemId) {
            const existingName = existingItem.nameTag;
            if (existingName === name) {
                return; // Item already correct
            }
        }
        const item = new ItemStack(itemId, 1);
        item.nameTag = name;
        item.setLore(lore);
        item.keepOnDeath = true;
        item.lockMode = ItemLockMode.slot;
        try {
            container.setItem(slot, item);
            // Lock the slot to prevent moving
            if (container.setLockMode) {
                container.setLockMode(slot, "slot");
            }
        }
        catch (error) {
            // Fallback if lock mode doesn't work
            container.setItem(slot, item);
        }
    }
    /**
     * Handle item usage
     */
    async handleItemUse(player, itemStack) {
        if (!itemStack || !this.isGameItem(itemStack))
            return;
        const itemName = itemStack.nameTag;
        switch (itemName) {
            case "§aStart Game":
                this.handleStartGame(player);
                break;
            case "§eSettings":
                await this.handleSettings(player);
                break;
            case "§bStats":
                this.handleStats(player);
                break;
            case "§6Last Checkpoint":
                this.handleCheckpoint(player);
                break;
            case "§cExit Run":
                this.handleExit(player);
                break;
        }
    }
    /**
     * Handle Start Game item
     */
    handleStartGame(player) {
        // Check if player has active run
        if (this.timeTracker.hasActiveRun(player.id)) {
            player.sendMessage("§cYou're already in a run! Use §eExit Run §cto quit first.");
            return;
        }
        // Find area with spawn point
        const spawnArea = this.findSpawnArea();
        if (!spawnArea) {
            player.sendMessage("§cNo spawn point found! An area needs to have a spawn point set.");
            return;
        }
        // Teleport to spawn point
        const spawn = spawnArea.data.spawnPoint;
        try {
            player.teleport({ x: spawn.x + 0.5, y: spawn.y, z: spawn.z + 0.5 }, {
                dimension: player.dimension,
                rotation: { x: spawn.pitch, y: spawn.yaw }
            });
        }
        catch (error) {
            player.sendMessage("§cFailed to teleport to spawn!");
            console.error(`Spawn teleport error: ${error}`);
        }
    }
    /**
     * Handle Settings item
     */
    async handleSettings(player) {
        await this.settingsUI.showSettingsMenu(player);
        player.playSound("note.pling");
    }
    /**
     * Handle Stats item
     */
    handleStats(player) {
        this.timeTrackerUI.showPlayerStats(player);
        player.playSound("note.pling");
    }
    /**
     * Handle Last Checkpoint item
     */
    handleCheckpoint(player) {
        // Check if player has active run
        if (!this.timeTracker.hasActiveRun(player.id)) {
            player.sendMessage("§cYou're not currently doing parkour!");
            return;
        }
        // Get current area
        const currentArea = this.timeTracker.getCurrentArea(player.id);
        if (!currentArea) {
            player.sendMessage("§cCouldn't find your current area!");
            return;
        }
        // Check if area has a checkpoint
        if (!currentArea.data.checkpoint) {
            player.sendMessage(`§cZone "${currentArea.data.name}" does not have a checkpoint!`);
            return;
        }
        // Teleport to checkpoint
        const checkpoint = currentArea.data.checkpoint;
        try {
            player.teleport({ x: checkpoint.x + 0.5, y: checkpoint.y, z: checkpoint.z + 0.5 }, {
                dimension: player.dimension,
                rotation: { x: checkpoint.pitch, y: checkpoint.yaw }
            });
            player.sendMessage(`§aTeleported to Checkpoint!`);
            player.playSound("random.orb");
        }
        catch (error) {
            player.sendMessage("§cFailed to teleport to checkpoint!");
        }
    }
    /**
     * Handle Exit item
     */
    handleExit(player) {
        // Check if player has active run
        if (!this.timeTracker.hasActiveRun(player.id)) {
            player.sendMessage("§cYou're not currently in a run!");
            return;
        }
        // End the run
        this.timeTracker.endRun(player.id);
        // Teleport to world spawn
        try {
            player.teleport({ x: -5, y: -23, z: 20 }, { dimension: player.dimension, rotation: { x: 0, y: -90 } });
        }
        catch (error) {
            // Teleport failed
        }
        player.sendMessage("§eRun ended. Returned to spawn.");
        player.playSound("random.orb");
        // Update items immediately
        this.updatePlayerItems(player);
    }
    /**
     * Find the area named "spawn" that has a spawn point set
     */
    findSpawnArea() {
        try {
            const allAreas = this.areaData.getAllAreasWithData();
            for (const area of allAreas) {
                if (area.data.isStartingArea && area.data.spawnPoint) {
                    return area;
                }
            }
            // Fallback: find area named "spawn"
            for (const area of allAreas) {
                if (area.data.name.toLowerCase() === "spawn" && area.data.spawnPoint) {
                    return area;
                }
            }
        }
        catch (error) {
            console.error("Error finding spawn area:", error);
        }
        return null;
    }
}
