setfenv(1, VoiceOver)

GameObjectAdapter = {}

local isActive = false
local playedObjects = {}

-- Función para obtener las coordenadas actuales del jugador
local function GetPlayerCoordinates()
    local mapID = C_Map.GetBestMapForUnit("player")
    if not mapID then
        return nil, nil
    end

    -- Usar RunScript para evitar error de Vector2DMixin en WoW 11.0+
    RunScript('_TEMP_POSITION = C_Map.GetPlayerMapPosition(' .. mapID .. ', "player")')

    local position = _G._TEMP_POSITION
    _G._TEMP_POSITION = nil

    if not position then
        return nil, nil
    end

    local x = position.x
    local y = position.y

    if not x or not y then
        return nil, nil
    end

    -- Convertir a porcentaje (0-100) y formatear con 1 decimal
    x = x * 100
    y = y * 100

    return x, y
end

-- Función para generar hash determinístico de 8 caracteres (FNV-1a)
-- Debe ser idéntico al de GameObjectOnlyFrame
local function GenerateHash(text)
    local FNV_OFFSET = 2166136261
    local FNV_PRIME = 16777619

    local hash = FNV_OFFSET
    for i = 1, #text do
        hash = bit.bxor(hash, string.byte(text, i))
        hash = (hash * FNV_PRIME) % 4294967296
    end

    return string.format("%08x", hash)
end

-- Función para obtener la ubicación actual del jugador como mapID y coordenadas
local function GetPlayerLocation()
    local mapID = C_Map.GetBestMapForUnit("player")
    if not mapID then
        return nil, nil
    end

    local x, y = GetPlayerCoordinates()
    if not x or not y then
        return nil, nil
    end

    -- Formato de coordenadas: "X.X,Y.Y" con 1 decimal
    local coords = string.format("%.1f,%.1f", x, y)

    return mapID, coords
end

-- Función para manejar ITEM_TEXT_READY
local function OnItemTextReady()
    if not isActive then
        print("|cffff0000[GameObject]|r Adapter is not active")
        return
    end

    local title = ItemTextGetItem()
    local mapID, coords = GetPlayerLocation()

    print("|cff00ff00[GameObject]|r ITEM_TEXT_READY triggered - Title:", title, "MapID:", mapID, "Coords:", coords)

    if not title or not mapID or not coords then
        print("|cffff0000[GameObject]|r Missing data - Title:", title, "MapID:", mapID, "Coords:", coords)
        return
    end

    -- Crear clave única para evitar duplicados
    local uniqueKey = title .. "|" .. mapID .. "|" .. coords

    if playedObjects[uniqueKey] then
        print("|cffffff00[GameObject]|r Already played:", uniqueKey)
        return -- Ya reproducido
    end

    -- 1. Intentar buscar en la base de datos de proximidad (oficial)
    local hash = DataModules:GetGameObjectHash(title, mapID, coords)
    
    -- 2. Si falla, intentar generar el hash directamente (para objetos convertidos manualmente)
    if not hash then
        local hashInput = title .. "|" .. mapID .. "|" .. coords
        local generatedHash = GenerateHash(hashInput)
        
        -- Verificar si este hash generado existe en algún módulo cargado
        if DataModules:GetSoundLength(generatedHash) then
            hash = generatedHash
            print("|cff00ffff[GameObject]|r Match found via generated hash:", hash)
        end
    else
        print("|cff00ff00[GameObject]|r Match found in database:", hash)
    end

    if not hash then
        local hashInput = title .. "|" .. mapID .. "|" .. coords
        local generatedHash = GenerateHash(hashInput)
        print("|cffff0000[GameObject]|r No match found. Title:", title, "MapID:", mapID, "Coords:", coords)
        print("|cffff0000[GameObject]|r Expected Hash:", generatedHash)
        return
    end

    -- Obtener duración del sonido
    local duration = DataModules:GetSoundLength(hash)
    local isManualFile = false
    
    if not duration then
        duration = 30 -- Duración por defecto para archivos manuales (más larga para asegurar que se escuche)
        isManualFile = true
        print("|cffffff00[GameObject]|r Using manual mode for hash:", hash)
    else
        print("|cff00ff00[GameObject]|r Sound duration found:", duration)
    end

    -- Crear soundData completo
    local soundData = {
        event = Enums.SoundEvent.GameObject,
        title = title,
        name = title,
        fileName = hash,
        filePath = format([[Interface\AddOns\AI_VoiceOverData_Midnight_esMX\generated\sounds\gameobjects\%s.mp3]], hash),
        length = duration,
    }

    -- Si es un archivo manual, intentamos registrarlo mínimamente para que SoundQueue no lo rechace
    if isManualFile then
        soundData.module = { METADATA = { AddonName = "AI_VoiceOverData_Midnight_esMX" } }
        SoundQueue:AddSoundToQueue(soundData)
        playedObjects[uniqueKey] = true
        print("|cff00ff00[GameObject]|r Manual sound added to queue")
    else
        -- Preparar y encolar el sonido (vía oficial)
        if DataModules:PrepareSound(soundData) then
            print("|cff00ff00[GameObject]|r Sound prepared, adding to queue")
            SoundQueue:AddSoundToQueue(soundData)
            playedObjects[uniqueKey] = true
        else
            print("|cffff0000[GameObject]|r Failed to prepare sound (not in tables?)")
        end
    end
end

-- Frame para eventos
local frame = CreateFrame("Frame")
frame:RegisterEvent("ITEM_TEXT_READY")

frame:SetScript("OnEvent", function(self, event, ...)
    if event == "ITEM_TEXT_READY" then
        OnItemTextReady()
    end
end)

-- Funciones de activación/desactivación
function GameObjectAdapter:Activate()
    isActive = true
end

function GameObjectAdapter:Deactivate()
    isActive = false
end

function GameObjectAdapter:Reset()
    playedObjects = {}
end
