LogiAgroLoader = {
    storages = {}, -- Tabela estática para guardar referências aos storages
    baseDirectory = g_currentModDirectory -- Diretório base definido como estático
}

local LogiAgroLoader_mt = Class(LogiAgroLoader)

function LogiAgroLoader:new()
    local self = setmetatable({}, LogiAgroLoader_mt)
    return self
end

function LogiAgroLoader:loadMap(name)
--     print("LogiAgroLoader carregado com sucesso!")
end

function LogiAgroLoader:getOrRegisterStorage(name)
    -- Verifica se o storage já está registrado
    if LogiAgroLoader.storages[name] then
        return LogiAgroLoader.storages[name]
    end

    -- Procura o storage nos placeables
    --print(string.format("Tentando registrar dinamicamente o Storage '%s'...", name))
    local placeables = g_currentMission.placeableSystem.placeables
    if placeables ~= nil then
        for _, placeable in ipairs(placeables) do
            if placeable:getName() == name then
                LogiAgroLoader.storages[name] = placeable
--                 print(string.format(">>>>>>>>>>>>>>>>>>>>>> Storage '%s' registrado dinamicamente.", name))
                return placeable
            end
        end
    end

--     print(string.format("Storage '%s' não encontrado para registro dinâmico.", name))
    return nil
end

function LogiAgroLoader:createStorage(name, x, y, z, rx, ry, rz)
    local storage = self:getOrRegisterStorage(name)
    if storage ~= nil then
        --print(string.format("Storage '%s' já existe. Nenhuma ação foi tomada.", name))
        return
    end

    local xmlFilePath = Utils.getFilename("storage.xml", LogiAgroLoader.baseDirectory)

    --print("Criando novo Storage com nome: " .. tostring(name))

    local placeableData = PlaceableLoadingData.new()
    placeableData:setFilename(xmlFilePath)
    placeableData:setPosition(x, y, z)
    placeableData:setRotation(rx, ry, rz)
    placeableData:setOwnerFarmId(g_currentMission:getFarmId())

    placeableData:load(function(_, newPlaceable, loadingState)
        if loadingState == PlaceableLoadingState.OK then
            g_currentMission:addOwnedItem(newPlaceable)
            newPlaceable:addToPhysics()
            g_currentMission.placeableSystem:addPlaceable(newPlaceable)

            -- Nomeia e registra o storage
            newPlaceable:setName(name)
            LogiAgroLoader.storages[name] = newPlaceable
            newPlaceable:setObjectStorageObjectInfosDirty()
--             print("Novo Storage registrado: " .. name)
        else
            --print("Erro ao criar o Storage: " .. tostring(loadingState))
        end
    end, self)
end

function LogiAgroLoader:deleteStorage(name)
    --print("Tentando excluir o Storage com nome: " .. tostring(name))

    local storage = self:getOrRegisterStorage(name)
    if storage == nil then
        --print("Erro: Storage com nome '" .. tostring(name) .. "' não encontrado!")
        return
    end

    -- Remove o storage do mapa
    if storage.removeFromPhysics then
        storage:removeFromPhysics()
    end
    if g_currentMission.placeableSystem then
        g_currentMission.placeableSystem:removePlaceable(storage)
    end

    -- Remove o storage da memória
    self.storages[name] = nil

    --print("Storage '" .. name .. "' excluído com sucesso!")
end

function LogiAgroLoader:makeStorageInvisible(name)
    --print("Tentando tornar invisível o Storage com nome: " .. tostring(name))

    local storage = self:getOrRegisterStorage(name)
    if storage == nil then
        --print("Erro: Storage com nome '" .. tostring(name) .. "' não encontrado!")
        return
    end

    setVisibility(storage.rootNode, false)
    removeFromPhysics(storage.rootNode)
    --print("Storage '" .. name .. "' tornou-se invisível.")
end

function LogiAgroLoader:makeStorageVisible(name)
    --print("Tentando tornar visível o Storage com nome: " .. tostring(name))

    local storage = self:getOrRegisterStorage(name)
    if storage == nil then
        --print("Erro: Storage com nome '" .. tostring(name) .. "' não encontrado!")
        return
    end

    setVisibility(storage.rootNode, true)
    addToPhysics(storage.rootNode)
    storage:setObjectStorageObjectInfosDirty()
    --print("Storage '" .. name .. "' tornou-se visível.")

    -- Garantir que 'shed_vis' permaneça invisível
    local shedVisNode = I3DUtil.indexToObject(storage.rootNode, "1")
    if shedVisNode then
        setVisibility(shedVisNode, false)
    end
end


function LogiAgroLoader:moveStorage(name, x, y, z, rx, ry, rz)
    --print("Tentando mover o Storage com nome: " .. tostring(name))

    local storage = self:getOrRegisterStorage(name)
    if storage == nil then
        --print("Erro: Storage com nome '" .. tostring(name) .. "' não encontrado!")
        return
    end

    local terrainHeight = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, x, 0, z)
    y = math.max(y, terrainHeight + 0.1)

    local storageRoot = storage.rootNode
    if not storageRoot then
        --print("Erro: Storage não possui um nó rootNode válido.")
        return
    end

    --print(string.format("Movendo Storage '%s' para nova posição: (%.2f, %.2f, %.2f)", name, x, y, z))

    removeFromPhysics(storageRoot)
    setWorldTranslation(storageRoot, x, y, z)
    setWorldRotation(storageRoot, rx, ry, rz)
    addToPhysics(storageRoot)

    --print("Storage '" .. name .. "' movido com sucesso!")
end

function LogiAgroLoader:setActiveSpawnArea(storageName, areaIndex)

    if areaIndex == nil then
        --print("Erro: Índice de área inválido. Recebido: (nil)")
        return
    end
    --print("Índice de área " .. tostring(areaIndex))

    local storage = self:getOrRegisterStorage(storageName)
    if storage == nil then
        --print("Erro: Storage com nome '" .. tostring(storageName) .. "' não encontrado!")
        return
    end

    -- Mapeamento das áreas e dos marcadores visuais
    local areaMappings = {
        {startPath = "0|10|0|0", endPath = "0|10|0|0|0", playerMarker = "0|10|2|1", objectMarker = "0|10|1|1"},
        {startPath = "0|10|0|1", endPath = "0|10|0|1|0", playerMarker = "0|10|2|2", objectMarker = "0|10|1|2"},
        {startPath = "0|10|0|2", endPath = "0|10|0|2|0", playerMarker = "0|10|2|3", objectMarker = "0|10|1|3"}
    }

    local area = areaMappings[areaIndex]
    if not area then
        --print(string.format("Erro: Índice de área inválido. Use 1, 2 ou 3. Recebido: %d", areaIndex))
        return
    end

    -- Identificar os nós principais
    local startNode = I3DUtil.indexToObject(storage.rootNode, area.startPath)
    local endNode = I3DUtil.indexToObject(storage.rootNode, area.endPath)
    local playerMarkerNode = I3DUtil.indexToObject(storage.rootNode, area.playerMarker)
    local objectMarkerNode = I3DUtil.indexToObject(storage.rootNode, area.objectMarker)

    if not startNode or not endNode or not playerMarkerNode or not objectMarkerNode then
        --print(string.format("Erro: Nós não encontrados para os caminhos definidos na área %d.", areaIndex))
        return
    end

    -- Atualizar área de spawn
    local spec = storage.spec_objectStorage
    if spec and spec.objectSpawn and spec.objectSpawn.area then
        spec.objectSpawn.area[1].startNode = startNode
        spec.objectSpawn.area[1].endNode = endNode

        setWorldTranslation(spec.objectSpawn.area[1].startNode, getWorldTranslation(startNode))
        setWorldTranslation(spec.objectSpawn.area[1].endNode, getWorldTranslation(endNode))

        --print(string.format("Área de spawn ativa movida para índice %d no storage '%s'.", areaIndex, storageName))

        if storage.updateObjectStorageVisualAreas then
            storage:updateObjectStorageVisualAreas()
        end

        if storage.setObjectStorageObjectInfosDirty then
            storage:setObjectStorageObjectInfosDirty()
        end
    else
        --print("Erro: Spec de storage inválido ou área de spawn não encontrada.")
    end

    -- Tornar visíveis os marcadores corretos e ocultar os outros
    for i, areaData in ipairs(areaMappings) do
        local playerMarker = I3DUtil.indexToObject(storage.rootNode, areaData.playerMarker)
        local objectMarker = I3DUtil.indexToObject(storage.rootNode, areaData.objectMarker)

        if playerMarker and objectMarker then
            local visible = (i == areaIndex)
            setVisibility(playerMarker, visible)
            setVisibility(objectMarker, visible)
        end
    end
end

addModEventListener(LogiAgroLoader:new())

--
-- Função para listar os pontos de produção do jogador no mapa e imprimir no console
-- function LogiAgroLoader:listPlayerProductionPoints()
--     -- Obtém todos os pontos de produção do mapa
--     local productionPoints = g_currentMission.productionPoints

--     if productionPoints == nil or #productionPoints == 0 then
--         print("Nenhum ponto de produção encontrado no mapa.")
--         return
--     end

--     print("Lista de Pontos de Produção do Jogador:")
--     for _, productionPoint in pairs(productionPoints) do
--         if productionPoint.ownerFarmId == g_currentMission:getFarmId() then
--             local name = productionPoint.name or "Desconhecido"
--             local type = productionPoint.typeName or "Desconhecido"

--             print(string.format("Nome: %s, Tipo: %s", name, type))
--         end
--     end
-- end


-- Mission00.onStartMission = Utils.appendedFunction(Mission00.onStartMission, function()
--     local loader = LogiAgroLoader:new()
--     loader:registerExistingStorages()
--     --loader:listPlayerProductionPoints()
-- end)

-- addModEventListener(LogiAgroLoader:new())