local widgets = {}

local function find(names)
  for _, name in ipairs(names) do
    local widget = rootWidget:recursiveGetChildById(name)
    if widget then return widget end
  end
  return nil
end

local function remember(name, widget)
  if widget then
    widgets[name] = widget
  end
end

local function applyLayout()
  if not g_game.isOnline() then return end

  -- Only coordinate widgets that already exist in this client.
  -- No placeholder widgets are created.
  remember('battle', find({'battleWindow', 'battleList', 'battlePanel'}))
  remember('inventory', find({'inventoryWindow', 'inventory', 'inventoryPanel'}))
  remember('minimap', find({'minimapWindow', 'minimap', 'minimapPanel'}))
  remember('console', find({'consoleWindow', 'gameConsole', 'consolePanel'}))

  -- Keep the existing map/game viewport authoritative.
  -- We intentionally do not force absolute positions here because
  -- different layouts can define their own anchors.
end

function init()
  connect(g_game, {
    onGameStart = applyLayout,
    onGameEnd = clear
  })

  scheduleEvent(applyLayout, 100)
end

function clear()
  widgets = {}
end

function terminate()
  disconnect(g_game, {
    onGameStart = applyLayout,
    onGameEnd = clear
  })
  widgets = {}
end
