-- Camada de interface: DOM via fengari-web (biblioteca `js`), input de
-- teclado e toque. Toda regra de jogo mora em logica/sokoban.lua — este
-- arquivo só desenha e traduz evento em chamada pra Sokoban.mover/desfazer.
--
-- Gotcha real descoberto testando: quando você registra um callback com
-- `elemento:addEventListener("evento", minhaFuncao)` (sintaxe de dois
-- pontos), o fengari-web chama a função Lua como `minhaFuncao(self, evento)`
-- — o primeiro parâmetro é o `this` do JS (o próprio elemento/window), o
-- evento de verdade vem no SEGUNDO parâmetro. Esquecer isso faz todo
-- `evento.key` etc. vir `nil` silenciosamente.

local js = require "js"
local document = js.global.document
local window = js.global.window

local nivelAtual = 1
local estado = nil

local elTabuleiro = document:getElementById("tabuleiro")
local elNomeNivel = document:getElementById("nome-nivel")
local elHud = document:getElementById("hud")
local elTelaFim = document:getElementById("tela-fim")
local elFimResumo = document:getElementById("fim-resumo")

local TAMANHO_CELULA = 42 -- px, precisa bater com --celula no styles.css

local function classeDaCelula(x, y)
  local k = x .. "," .. y
  if estado.paredes[k] then
    return "celula parede"
  end

  local partes = { "celula" }
  local temAlvo = estado.alvos[k]
  local temCaixa = estado.caixas[k]
  local temJogador = estado.jogador.x == x and estado.jogador.y == y

  if temAlvo then table.insert(partes, "alvo") end
  if temCaixa then
    table.insert(partes, temAlvo and "caixa-no-alvo" or "caixa")
  end
  if temJogador then
    table.insert(partes, temAlvo and "jogador-no-alvo" or "jogador")
  end

  return table.concat(partes, " ")
end

local function renderizar()
  elTabuleiro.innerHTML = ""
  elTabuleiro.style.gridTemplateColumns = "repeat(" .. estado.largura .. ", " .. TAMANHO_CELULA .. "px)"
  elTabuleiro.style.gridTemplateRows = "repeat(" .. estado.altura .. ", " .. TAMANHO_CELULA .. "px)"

  for y = 1, estado.altura do
    for x = 1, estado.largura do
      local div = document:createElement("div")
      div.className = classeDaCelula(x, y)
      elTabuleiro:appendChild(div)
    end
  end

  elHud.textContent = "Movimentos: " .. estado.movimentos

  if Sokoban.venceu(estado) then
    elFimResumo.textContent = "Resolvido em " .. estado.movimentos .. " movimento(s)."
    elTelaFim:removeAttribute("hidden")
  else
    elTelaFim:setAttribute("hidden", "")
  end
end

local function carregarNivelAtual()
  local nivel = Sokoban.NIVEIS[nivelAtual]
  estado = Sokoban.carregarNivel(nivel.texto)
  elNomeNivel.textContent = "Nível " .. nivelAtual .. " de " .. #Sokoban.NIVEIS .. ": " .. nivel.nome
  renderizar()
end

local function mover(direcao)
  estado = Sokoban.mover(estado, direcao)
  renderizar()
end

local function desfazer()
  estado = Sokoban.desfazer(estado)
  renderizar()
end

local function proximoNivel()
  if nivelAtual < #Sokoban.NIVEIS then
    nivelAtual = nivelAtual + 1
  else
    nivelAtual = 1
  end
  carregarNivelAtual()
end

-- Teclado (desktop)
local TECLA_PARA_DIRECAO = {
  ArrowUp = "cima",
  ArrowDown = "baixo",
  ArrowLeft = "esquerda",
  ArrowRight = "direita",
}

local function aoTeclar(self, evento)
  local direcao = TECLA_PARA_DIRECAO[evento.key]
  if direcao then
    evento:preventDefault()
    mover(direcao)
    return
  end
  if evento.key == "z" or evento.key == "u" then
    desfazer()
  elseif evento.key == "r" then
    carregarNivelAtual()
  end
end
window:addEventListener("keydown", aoTeclar)

-- Botões na tela (funciona em toque e em clique de mouse)
local function ligarBotao(id, funcao)
  local el = document:getElementById(id)
  el:addEventListener("click", function(self, evento)
    funcao()
  end)
end

ligarBotao("btn-cima", function() mover("cima") end)
ligarBotao("btn-baixo", function() mover("baixo") end)
ligarBotao("btn-esquerda", function() mover("esquerda") end)
ligarBotao("btn-direita", function() mover("direita") end)
ligarBotao("btn-desfazer", desfazer)
ligarBotao("btn-proximo", proximoNivel)

carregarNivelAtual()
