import { POKEMONS_DATA } from "../data/pokemon.js";
import { MOVEMENTS_DATA } from "../data/movement.js";
import { Debugger } from "../api/debugger.js";
const debug = Debugger.getInstance();
class SlotDataManager {
    // Mapas para converter IDs longos em códigos curtos
    pokemonIdMap = new Map();
    movementIdMap = new Map();
    reversePokemonIdMap = new Map();
    reverseMovementIdMap = new Map();
    constructor() {
        this.initializeMaps();
    }
    initializeMaps() {
        // Criar mapeamento para Pokémon (usando índice como código)
        POKEMONS_DATA.forEach((pokemon, index) => {
            const shortCode = this.encodeNumber(index);
            this.pokemonIdMap.set(pokemon.id, shortCode);
            this.reversePokemonIdMap.set(shortCode, pokemon.id);
        });
        // Criar mapeamento para movimentos (usando índice como código)
        MOVEMENTS_DATA.forEach((movement, index) => {
            const shortCode = this.encodeNumber(index);
            this.movementIdMap.set(movement.id, shortCode);
            this.reverseMovementIdMap.set(shortCode, movement.id);
        });
    }
    // Codifica números em base 62 (0-9, a-z, A-Z) para economizar espaço
    encodeNumber(num) {
        const chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
        if (num === 0)
            return '0';
        let result = '';
        while (num > 0) {
            result = chars[num % 62] + result;
            num = Math.floor(num / 62);
        }
        return result;
    }
    // Decodifica números da base 62
    decodeNumber(str) {
        const chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
        let result = 0;
        for (let i = 0; i < str.length; i++) {
            result = result * 62 + chars.indexOf(str[i]);
        }
        return result;
    }
    // Codifica os dados do slot em uma string compacta
    encodePokemonSlotData(data) {
        const parts = [
            data.health.toString(),
            data.level.toString(),
            data.xp.toString(),
            this.pokemonIdMap.get(data.typeId) || '0',
            data.name,
            data.owner,
            data.attack.toString(),
            data.defense.toString(),
            data.speed.toString(),
            data.spAttack.toString(),
            data.spDefense.toString(),
            this.movementIdMap.get(data.move1) || '0',
            this.movementIdMap.get(data.move2) || '0',
            this.movementIdMap.get(data.move3) || '0',
            this.movementIdMap.get(data.move4) || '0'
        ];
        // Usar um separador eficiente (|)
        const encoded = parts.join('|');
        // Verificar se excede o limite de 255 caracteres
        if (encoded.length > 255) {
            throw new Error(`Dados codificados excedem 255 caracteres: ${encoded.length}`);
        }
        return encoded;
    }
    // Decodifica a string compacta para os dados do slot
    decodePokemonSlotData(encodedData) {
        if (!encodedData || encodedData.trim() === '') {
            debug.log(`decodePokemonSlotData: encodedData is empty or null`);
            return null;
        }
        try {
            const parts = encodedData.split('|');
            debug.log(`decodePokemonSlotData: parts length = ${parts.length}, expected 15`);
            debug.log(`decodePokemonSlotData: parts = ${JSON.stringify(parts)}`);
            if (parts.length !== 15) {
                debug.log(`decodePokemonSlotData: Wrong parts length, returning null`);
                return null;
            }
            const decoded = {
                health: parseInt(parts[0]) || 0,
                level: parseInt(parts[1]) || 1,
                xp: parseInt(parts[2]) || 0,
                typeId: this.reversePokemonIdMap.get(parts[3]) || '',
                name: parts[4] || '',
                owner: parts[5] || '',
                attack: parseInt(parts[6]) || 0,
                defense: parseInt(parts[7]) || 0,
                speed: parseInt(parts[8]) || 0,
                spAttack: parseInt(parts[9]) || 0,
                spDefense: parseInt(parts[10]) || 0,
                move1: this.reverseMovementIdMap.get(parts[11]) || '',
                move2: this.reverseMovementIdMap.get(parts[12]) || '',
                move3: this.reverseMovementIdMap.get(parts[13]) || '',
                move4: this.reverseMovementIdMap.get(parts[14]) || ''
            };
            debug.log(`decodePokemonSlotData: decoded = ${JSON.stringify(decoded)}`);
            return decoded;
        }
        catch (error) {
            console.error('Erro ao decodificar dados do slot:', error);
            return null;
        }
    }
    // Define os dados de um slot específico
    setPokemonSlotData(player, slotIndex, data) {
        if (slotIndex < 0 || slotIndex > 5) {
            throw new Error('Índice do slot deve estar entre 0 e 5');
        }
        const encodedData = this.encodePokemonSlotData(data);
        player.setDynamicProperty(`rp_pr:pokemon_slot_${slotIndex}`, encodedData);
    }
    // Obtém os dados de um slot específico
    getPokemonSlotData(player, slotIndex) {
        if (slotIndex < 0 || slotIndex > 5) {
            throw new Error('Índice do slot deve estar entre 0 e 5');
        }
        const encodedData = player.getDynamicProperty(`rp_pr:pokemon_slot_${slotIndex}`);
        return this.decodePokemonSlotData(encodedData);
    }
    // Obtém todos os slots do jogador
    getAllPokemonSlots(player) {
        const slots = [];
        for (let i = 0; i < 6; i++) {
            slots.push(this.getPokemonSlotData(player, i));
        }
        return slots;
    }
    // Limpa um slot específico
    clearPokemonSlot(player, slotIndex) {
        if (slotIndex < 0 || slotIndex > 5) {
            throw new Error('Índice do slot deve estar entre 0 e 5');
        }
        player.setDynamicProperty(`rp_pr:pokemon_slot_${slotIndex}`, '');
    }
    // Encontra o primeiro slot vazio
    findFirstEmptySlot(player) {
        for (let i = 0; i < 6; i++) {
            const slotData = this.getPokemonSlotData(player, i);
            if (!slotData) {
                return i;
            }
        }
        return -1; // Nenhum slot vazio encontrado
    }
    // Adiciona um Pokémon ao primeiro slot disponível
    addPokemonToSlot(player, pokemonData) {
        const emptySlot = this.findFirstEmptySlot(player);
        if (emptySlot === -1) {
            return false; // Nenhum slot disponível
        }
        this.setPokemonSlotData(player, emptySlot, pokemonData);
        return true;
    } // Métodos para PC System
    // Codifica dados do PC usando compactação simples
    encodePCData(pcData) {
        try {
            // Usar codificação similar ao sistema de slots existente
            const pokemonStrings = pcData.pokemons.map(pokemon => {
                const parts = [
                    pokemon.health.toString(),
                    pokemon.level.toString(),
                    pokemon.xp.toString(),
                    this.pokemonIdMap.get(pokemon.typeId) || '0',
                    pokemon.name,
                    pokemon.owner,
                    pokemon.attack.toString(),
                    pokemon.defense.toString(),
                    pokemon.speed.toString(),
                    pokemon.spAttack.toString(),
                    pokemon.spDefense.toString(),
                    this.movementIdMap.get(pokemon.move1) || '0',
                    this.movementIdMap.get(pokemon.move2) || '0',
                    this.movementIdMap.get(pokemon.move3) || '0',
                    this.movementIdMap.get(pokemon.move4) || '0'
                ];
                return parts.join('|');
            });
            // Juntar todos os Pokémon com separador `;`
            return pokemonStrings.join(';');
        }
        catch (error) {
            console.error('Erro ao codificar dados do PC:', error);
            return '';
        }
    }
    // Decodifica dados do PC
    decodePCData(encodedData) {
        try {
            if (!encodedData || encodedData.trim() === '') {
                return { pokemons: [] };
            }
            const pokemonStrings = encodedData.split(';');
            const pokemons = [];
            for (const pokemonString of pokemonStrings) {
                if (!pokemonString || pokemonString.trim() === '')
                    continue;
                const parts = pokemonString.split('|');
                if (parts.length !== 15)
                    continue;
                const pokemon = {
                    health: parseInt(parts[0]) || 0,
                    level: parseInt(parts[1]) || 1,
                    xp: parseInt(parts[2]) || 0,
                    typeId: this.reversePokemonIdMap.get(parts[3]) || '',
                    name: parts[4] || '',
                    owner: parts[5] || '',
                    attack: parseInt(parts[6]) || 0,
                    defense: parseInt(parts[7]) || 0,
                    speed: parseInt(parts[8]) || 0,
                    spAttack: parseInt(parts[9]) || 0,
                    spDefense: parseInt(parts[10]) || 0,
                    move1: this.reverseMovementIdMap.get(parts[11]) || '',
                    move2: this.reverseMovementIdMap.get(parts[12]) || '',
                    move3: this.reverseMovementIdMap.get(parts[13]) || '',
                    move4: this.reverseMovementIdMap.get(parts[14]) || ''
                };
                // Só adiciona se o Pokémon for válido
                if (pokemon.typeId) {
                    pokemons.push(pokemon);
                }
            }
            return { pokemons };
        }
        catch (error) {
            console.error('Erro ao decodificar dados do PC:', error);
            console.error('Dados codificados:', encodedData);
            return { pokemons: [] };
        }
    }
    // Inicializa o PC do jogador
    initializePlayerPC(player) {
        const existingPC = player.getDynamicProperty('pr:pc_data');
        if (!existingPC) {
            const initialPC = { pokemons: [] };
            const encodedPC = this.encodePCData(initialPC);
            player.setDynamicProperty('pr:pc_data', encodedPC);
        }
    }
    // Obtém dados do PC do jogador
    getPlayerPCData(player) {
        const encodedData = player.getDynamicProperty('pr:pc_data');
        const pcData = this.decodePCData(encodedData);
        return pcData || { pokemons: [] };
    }
    // Salva dados do PC do jogador
    savePlayerPCData(player, pcData) {
        try {
            const encodedData = this.encodePCData(pcData);
            player.setDynamicProperty('pr:pc_data', encodedData);
            return true;
        }
        catch (error) {
            console.error('Erro ao salvar dados do PC:', error);
            return false;
        }
    }
    // Adiciona Pokémon ao PC
    addPokemonToPC(player, pokemonData) {
        try {
            const pcData = this.getPlayerPCData(player);
            pcData.pokemons.push(pokemonData);
            return this.savePlayerPCData(player, pcData);
        }
        catch (error) {
            console.error('Erro ao adicionar Pokémon ao PC:', error);
            return false;
        }
    }
    // Remove Pokémon do PC por índice
    removePokemonFromPC(player, pcIndex) {
        try {
            const pcData = this.getPlayerPCData(player);
            if (pcIndex >= 0 && pcIndex < pcData.pokemons.length) {
                pcData.pokemons.splice(pcIndex, 1);
                return this.savePlayerPCData(player, pcData);
            }
            return false;
        }
        catch (error) {
            console.error('Erro ao remover Pokémon do PC:', error);
            return false;
        }
    }
    // Obtém Pokémon específico do PC
    getPokemonFromPC(player, pcIndex) {
        try {
            const pcData = this.getPlayerPCData(player);
            if (pcIndex >= 0 && pcIndex < pcData.pokemons.length) {
                return pcData.pokemons[pcIndex];
            }
            return null;
        }
        catch (error) {
            console.error('Erro ao obter Pokémon do PC:', error);
            return null;
        }
    }
    // Move Pokémon do slot para o PC
    movePokemonToPC(player, slotIndex) {
        try {
            const pokemonData = this.getPokemonSlotData(player, slotIndex);
            if (!pokemonData)
                return false;
            const success = this.addPokemonToPC(player, pokemonData);
            if (success) {
                this.clearPokemonSlot(player, slotIndex);
            }
            return success;
        }
        catch (error) {
            console.error('Erro ao mover Pokémon para PC:', error);
            return false;
        }
    }
    // Move Pokémon do PC para slot
    movePokemonFromPC(player, pcIndex, slotIndex) {
        try {
            const pokemonData = this.getPokemonFromPC(player, pcIndex);
            if (!pokemonData)
                return false;
            // Verifica se o slot está vazio
            const existingSlotData = this.getPokemonSlotData(player, slotIndex);
            if (existingSlotData)
                return false;
            // Move o Pokémon
            this.setPokemonSlotData(player, slotIndex, pokemonData);
            this.removePokemonFromPC(player, pcIndex);
            return true;
        }
        catch (error) {
            console.error('Erro ao mover Pokémon do PC:', error);
            return false;
        }
    }
    // Obtém contagem de Pokémon no PC
    getPCPokemonCount(player) {
        const pcData = this.getPlayerPCData(player);
        return pcData.pokemons.length;
    }
    // Debug: mostra o tamanho dos dados codificados
    debugSlotSize(data) {
        try {
            const encoded = this.encodePokemonSlotData(data);
            console.log(`Dados codificados: ${encoded}`);
            console.log(`Tamanho: ${encoded.length}/255 caracteres`);
            const decoded = this.decodePokemonSlotData(encoded);
            console.log('Dados decodificados:', decoded);
        }
        catch (error) {
            console.error('Erro no debug:', error);
        }
    }
}
export const slotDataManager = new SlotDataManager();
