-- The forget-a-move text is not one uninterrupted string: pokered's
-- OneTwoAndText holds the box with text_pause, plays SFX_SWAP, prints
-- " Poof!" and holds it again before the paragraph break
-- (engine/pokemon/learn_move.asm:208-222, home/text.asm:492-504).  The port
-- typed all of it straight through in silence (#1818).  TextBox.PAUSE now
-- carries those waits inside the string, with opts.pauseSounds naming the
-- sfx each one fires.  ROM-free.
--   luajit tests/engine/textbox_pause_bug1818.lua

package.path = "./?.lua;./?/init.lua;" .. package.path

local T = require("tests.harness")
local check, eq = T.check, T.eq
love = love or require("tests.love_stub")

local TextBox = require("src.render.TextBox")
local MoveLearnMenu = require("src.ui.MoveLearnMenu")
local Sound = require("src.core.Sound")

local played = {}
local realPlay = Sound.play
Sound.play = function(data, name)
  played[#played + 1] = name
  return nil
end

local function newGame()
  local game = {
    save = { player = {}, options = { textSpeed = "FAST" } },
    data = { text = {}, moves = { MEGA_PUNCH = { name = "MEGA PUNCH" } },
             pokemon = { NIDORINO = { name = "NIDORINO" } } },
  }
  game.stack = {
    states = {},
    push = function(self, s) table.insert(self.states, s) end,
    pop = function(self) return table.remove(self.states) end,
    top = function(self) return self.states[#self.states] end,
  }
  game.input = {
    queue = {},
    wasPressed = function(self, btn) return self.queue[btn] or false end,
    isDown = function(self, btn) return self.queue[btn] or false end,
  }
  return game
end

local game = newGame()
local box = TextBox.new(game, "1, 2 and..." .. TextBox.PAUSE .. " Poof!",
                        nil, { pauseSounds = { "Swap" } })

eq(box.pages[1][1], "1, 2 and... Poof!",
   "the marker is stripped out of the line the font ever sees")
check(box.pauseAt and box.pauseAt[1] and box.pauseAt[1][1],
      "the pause is re-anchored onto page 1, line 1")
eq(box.pauseAt[1][1][11], 1, "it sits on the 11th glyph, the last of \"1, 2 and...\"")

-- type up to the marker
local frames = 0
while not box.pauseFrames and frames < 600 do
  box:update(1 / 60)
  frames = frames + 1
end
check(box.pauseFrames, "typing stops at the marker")
eq(box.charIndex, 11, "it stops with \"1, 2 and...\" printed and nothing after it")
eq(#played, 0, "SFX_SWAP has not sounded yet -- the wait comes first")

local frozen = box.charIndex
for _ = 1, 31 do
  box:update(1 / 60)
  if #played > 0 then break end
  eq(box.charIndex, frozen, "nothing types while the pause runs")
end
eq(played[1], "Swap", "the wait ends with SFX_SWAP (learn_move.asm:210-213)")

for _ = 1, 600 do
  if box.done then break end
  box:update(1 / 60)
end
check(box.done, "\" Poof!\" types out after the sound")
eq(box.charIndex, 17, "the whole line printed, marker included in nothing")

-- a held A/B skips the wait: TextCommand_PAUSE reads hJoyHeld
local held = newGame()
held.input.queue = { a = true }
local box2 = TextBox.new(held, "1, 2 and..." .. TextBox.PAUSE .. " Poof!",
                         nil, { pauseSounds = { "Swap" } })
local before = #played
for _ = 1, 40 do
  if box2.done then break end
  box2:update(1 / 60)
end
check(box2.done, "with A held the box runs straight through the pause")
check(#played > before, "the sound still plays on the skipped wait")

-- and the real caller wires both waits with the swap on the first
local mlm = MoveLearnMenu.new(game, { species = "NIDORINO", level = 20,
                                      moves = {} }, "MEGA_PUNCH")
mlm.forgot = "HORN ATTACK"
game.stack:push(mlm)
mlm:finish(true)
local learned = game.stack:top()
check(learned.pauseAt, "the learned-move box carries text_pause waits")
eq(learned.pauseSounds[1], "Swap", "the first wait carries SFX_SWAP")
local count = 0
for _, lines in pairs(learned.pauseAt) do
  for _, chars in pairs(lines) do
    for _ in pairs(chars) do count = count + 1 end
  end
end
eq(count, 2, "both of learn_move.asm's text_pause commands survive")

Sound.play = realPlay
T.finish()
