import { world, system } from '@minecraft/server';
/**
 * Leaderboard types
 */
export var LeaderboardType;
(function (LeaderboardType) {
    LeaderboardType["BEST_TIME"] = "best_time";
    LeaderboardType["TOTAL_PLAYTIME"] = "total_playtime";
    LeaderboardType["BEST_SEGMENT"] = "best_segment";
})(LeaderboardType || (LeaderboardType = {}));
/**
 * Handler for hologram leaderboard entities
 */
export class LeaderboardHologram {
    timeTracker;
    updateInterval = 100; // Update every 5 seconds (100 ticks)
    constructor(timeTracker) {
        this.timeTracker = timeTracker;
        this.startAutoUpdate();
    }
    /**
     * Spawn a leaderboard hologram at a location
     */
    spawnLeaderboard(dimension, location, type) {
        try {
            const entity = dimension.spawnEntity('mbl:hologram', location);
            // Add tags to identify the hologram
            entity.addTag('leaderboard');
            entity.addTag(`leaderboard_${type}`);
            // Initial update
            this.updateLeaderboard(entity, type);
            return entity;
        }
        catch (error) {
            return null;
        }
    }
    /**
     * Update a specific leaderboard hologram
     */
    updateLeaderboard(entity, type) {
        try {
            let nameTag = '';
            switch (type) {
                case LeaderboardType.BEST_TIME:
                    nameTag = this.generateBestTimeLeaderboard();
                    break;
                case LeaderboardType.TOTAL_PLAYTIME:
                    nameTag = this.generateTotalPlaytimeLeaderboard();
                    break;
                case LeaderboardType.BEST_SEGMENT:
                    nameTag = this.generateBestSegmentLeaderboard();
                    break;
            }
            entity.nameTag = nameTag;
        }
        catch (error) {
            // Failed to update leaderboard
        }
    }
    /**
     * Generate best time leaderboard display
     */
    generateBestTimeLeaderboard() {
        const leaderboard = this.timeTracker.getLeaderboard();
        const topN = 10;
        let display = '§6§l=== BEST TIMES ===§r\n\n';
        for (let i = 0; i < topN; i++) {
            const rank = i + 1;
            const rankStr = rank < 10 ? `${rank}. ` : `${rank}.`;
            if (i < leaderboard.length) {
                const entry = leaderboard[i];
                const timeFormatted = this.timeTracker.formatTimeCompact(entry.totalTime);
                // Color coding for top 3
                let color = '§7';
                if (rank === 1)
                    color = '§6';
                else if (rank === 2)
                    color = '§f';
                else if (rank === 3)
                    color = '§c';
                display += `${color}${rankStr} §f${entry.playerName} §7- §e${timeFormatted}\n`;
            }
            else {
                // Empty slot with "Unclaimed"
                display += `§8${rankStr} §8Unclaimed\n`;
            }
        }
        return display;
    }
    /**
     * Generate total playtime leaderboard display
     */
    generateTotalPlaytimeLeaderboard() {
        const playersData = this.getAllPlayersPlaytime();
        const topN = 10;
        let display = '§6§l=== TOTAL PLAYTIME ===§r\n\n';
        // Sort by total playtime (descending)
        playersData.sort((a, b) => b.totalTime - a.totalTime);
        for (let i = 0; i < topN; i++) {
            const rank = i + 1;
            const rankStr = rank < 10 ? `${rank}. ` : `${rank}.`;
            if (i < playersData.length) {
                const player = playersData[i];
                const timeFormatted = this.formatPlaytime(player.totalTime);
                // Color coding for top 3
                let color = '§7';
                if (rank === 1)
                    color = '§6';
                else if (rank === 2)
                    color = '§f';
                else if (rank === 3)
                    color = '§c';
                display += `${color}${rankStr} §f${player.name} §7- §e${timeFormatted}\n`;
            }
            else {
                // Empty slot with "Unclaimed"
                display += `§8${rankStr} §8Unclaimed\n`;
            }
        }
        return display;
    }
    /**
     * Generate best segment leaderboard display
     * Shows each player's single best segment time only
     */
    generateBestSegmentLeaderboard() {
        const playerBestSegments = this.getPlayerBestSegments();
        const topN = 10;
        let display = '§6§l=== BEST GRID TIME ===§r\n\n';
        for (let i = 0; i < topN; i++) {
            const rank = i + 1;
            const rankStr = rank < 10 ? `${rank}. ` : `${rank}.`;
            if (i < playerBestSegments.length) {
                const segment = playerBestSegments[i];
                const timeFormatted = this.timeTracker.formatTimeCompact(segment.duration);
                // Color coding for top 3
                let color = '§7';
                if (rank === 1)
                    color = '§6';
                else if (rank === 2)
                    color = '§f';
                else if (rank === 3)
                    color = '§c';
                display += `${color}${rankStr} §f${segment.playerName} §7(${segment.areaName}) §e${timeFormatted}\n`;
            }
            else {
                // Empty slot
                display += `§8${rankStr} §8Unclaimed\n`;
            }
        }
        return display;
    }
    /**
     * Get all players' total playtime from completed runs
     */
    getAllPlayersPlaytime() {
        const playersMap = new Map();
        try {
            const objective = world.scoreboard.getObjective('time_tracker_db');
            if (!objective)
                return [];
            const participants = objective.getParticipants();
            for (const participant of participants) {
                try {
                    const run = JSON.parse(participant.displayName);
                    if (!playersMap.has(run.playerId)) {
                        playersMap.set(run.playerId, {
                            name: run.playerName,
                            totalTime: 0,
                            runs: 0
                        });
                    }
                    const playerData = playersMap.get(run.playerId);
                    playerData.totalTime += run.totalDuration;
                    playerData.runs += 1;
                }
                catch {
                    continue;
                }
            }
        }
        catch (error) {
            // Failed to get playtime
        }
        return Array.from(playersMap.entries()).map(([playerId, data]) => ({
            playerId,
            name: data.name,
            totalTime: data.totalTime,
            runs: data.runs
        }));
    }
    /**
     * Get best segment times across all runs
     */
    getBestSegmentTimes() {
        const segmentMap = new Map();
        try {
            const objective = world.scoreboard.getObjective('time_tracker_db');
            if (!objective)
                return [];
            const participants = objective.getParticipants();
            for (const participant of participants) {
                try {
                    const run = JSON.parse(participant.displayName);
                    for (const segment of run.segmentTimes) {
                        const key = `${segment.fromAreaName}→${segment.toAreaName}`;
                        if (!segmentMap.has(key) || segment.duration < segmentMap.get(key).duration) {
                            segmentMap.set(key, {
                                playerName: run.playerName,
                                duration: segment.duration
                            });
                        }
                    }
                }
                catch {
                    continue;
                }
            }
        }
        catch (error) {
            // Failed to get segment times
        }
        // Convert to array and sort by duration
        return Array.from(segmentMap.entries())
            .map(([key, data]) => {
            const [fromArea, toArea] = key.split('→');
            return {
                playerName: data.playerName,
                fromArea,
                toArea,
                duration: data.duration
            };
        })
            .sort((a, b) => a.duration - b.duration);
    }
    /**
     * Get each player's single best segment time
     */
    getPlayerBestSegments() {
        const playerBestMap = new Map();
        try {
            const objective = world.scoreboard.getObjective('time_tracker_db');
            if (!objective)
                return [];
            const participants = objective.getParticipants();
            for (const participant of participants) {
                try {
                    const run = JSON.parse(participant.displayName);
                    for (const segment of run.segmentTimes) {
                        const playerId = run.playerId;
                        // Only keep the best segment for each player
                        if (!playerBestMap.has(playerId) || segment.duration < playerBestMap.get(playerId).duration) {
                            playerBestMap.set(playerId, {
                                areaName: segment.toAreaName,
                                duration: segment.duration
                            });
                        }
                    }
                }
                catch {
                    continue;
                }
            }
            // Get player names
            const results = [];
            for (const participant of participants) {
                try {
                    const run = JSON.parse(participant.displayName);
                    if (playerBestMap.has(run.playerId)) {
                        const bestSegment = playerBestMap.get(run.playerId);
                        // Check if we already added this player
                        if (!results.find(r => r.playerName === run.playerName)) {
                            results.push({
                                playerName: run.playerName,
                                areaName: bestSegment.areaName,
                                duration: bestSegment.duration
                            });
                        }
                    }
                }
                catch {
                    continue;
                }
            }
            // Sort by duration (fastest first)
            return results.sort((a, b) => a.duration - b.duration);
        }
        catch (error) {
            console.error(`Failed to get player best segments: ${error}`);
        }
        return [];
    }
    /**
     * Format playtime to readable format (HH:MM:SS)
     */
    formatPlaytime(milliseconds) {
        const totalSeconds = Math.floor(milliseconds / 1000);
        const hours = Math.floor(totalSeconds / 3600);
        const minutes = Math.floor((totalSeconds % 3600) / 60);
        const seconds = totalSeconds % 60;
        if (hours > 0) {
            return `${hours}h ${minutes}m ${seconds}s`;
        }
        else if (minutes > 0) {
            return `${minutes}m ${seconds}s`;
        }
        else {
            return `${seconds}s`;
        }
    }
    /**
     * Start automatic leaderboard updates
     */
    startAutoUpdate() {
        system.runInterval(() => {
            this.updateAllLeaderboards();
        }, this.updateInterval);
    }
    /**
     * Update all leaderboard holograms in the world
     */
    /**
     * Update all leaderboard holograms in the world
     */
    updateAllLeaderboards() {
        try {
            const dimension = world.getDimension('overworld');
            const entities = dimension.getEntities({ type: 'mbl:hologram', tags: ['leaderboard'] });
            for (const entity of entities) {
                const tags = entity.getTags();
                if (tags.includes('leaderboard_best_time')) {
                    this.updateLeaderboard(entity, LeaderboardType.BEST_TIME);
                }
                else if (tags.includes('leaderboard_total_playtime')) {
                    this.updateLeaderboard(entity, LeaderboardType.TOTAL_PLAYTIME);
                }
                else if (tags.includes('leaderboard_best_segment')) {
                    this.updateLeaderboard(entity, LeaderboardType.BEST_SEGMENT);
                }
            }
        }
        catch (error) {
            // Failed to update leaderboards
        }
    }
}
