-- EVENT_TEMPORARY_UNTIL_MAP_RELOAD: HandleNewMap calls
-- ResetMapBufferEventFlags on every map load (pokegold home/map.asm), and
-- home/flag.asm shows that routine zeroing exactly ONE byte of wEventFlags --
-- flags 0-7.  Those eight are the once-per-visit latches: Bill's grandpa sets
-- flag 0 after handing over an evolution stone and refuses while it is set,
-- so a port that never clears the byte caps his whole chain at one stone per
-- save.  Kurt's house, the ship ports, Dragon's Den B1F, the National Park
-- gate, Pokecenter 2F and the link rooms ride the same byte.
--
--   GOLD_CACHE=".../gold" luajit tests/gen2_temp_events_test.lua
--
-- The clear and its ordering are ROM-free; the Bill's-house shape SKIPs
-- without a cache.
package.path = "./?.lua;./?/init.lua;" .. package.path

local S = require("tests.harness").suite("gen2 temp events")
local check, eq = S.check, S.eq

love = require("tests.love_stub")

local World = require("src.world.gen2.World")
local Events = require("src.world.gen2.Events")
local Vm = require("src.script.gen2.Vm")
local Map = require("src.world.gen2.Map")

-- ---- the byte itself -------------------------------------------------------
do
  local events = Events.new()
  for id = 0, 9 do events:set(id, true) end
  events:set(800, true)
  events:resetMapBuffer()
  for id = 0, 7 do
    check(not events:get(id), ("flag %d dies with the map"):format(id))
  end
  check(events:get(8), "flag 8 is the next byte and survives")
  check(events:get(9), "so does flag 9")
  check(events:get(800), "and a story flag is untouched")
end

-- ---- the clear rides setMap, BEFORE MAPCALLBACK_NEWMAP ---------------------
-- The callback order test rig from gen2_map_callbacks_test: real setMap, the
-- love-facing bakes stubbed out.  The NEWMAP body itself checks flag 0, which
-- pins the order -- a clear that ran after the callback would read 1 here.
do
  local world = World.new({ data = {}, save = { party = {}, inventory = {} } })
  world.maps = {
    TEST_MAP = { id = "TEST_MAP", group = 1, map = 2, width = 2, height = 2,
      blocks = { 1, 2, 3, 4 }, objects = {}, warps = {}, tileset = "TEST",
      callbacks = {
        { callback = "MAPCALLBACK_NEWMAP", scriptKey = "newmap" },
      } },
  }
  world.tilesets = { TEST = {} }
  world.map = Map.new(world.maps.TEST_MAP, {})
  world.scripts = {
    newmap = {
      { op = "checkevent", event = 0 },
      { op = "iftrue", script = "sawset" },
      { op = "setevent", event = 600 },
      { op = "endcallback" },
    },
    sawset = { { op = "setevent", event = 601 }, { op = "endcallback" } },
  }
  world.vm = Vm.new(world.scripts, {}, world.events, {})
  world.imageFor = function() return true end
  world.rebuildNeighbors = function() end
  world.rebuildPeople = function() end
  world.applyPalettes = function() end

  for id = 0, 8 do world.events:set(id, true) end
  check(world:setMap("TEST_MAP", 0, 0, "down"), "the map loads")
  for id = 0, 7 do
    check(not world.events:get(id),
      ("setMap cleared temporary flag %d"):format(id))
  end
  check(world.events:get(8), "and left flag 8 alone")
  check(world.events:get(600), "the NEWMAP callback saw flag 0 already clear")
  check(not world.events:get(601),
    "so the clear really runs before MAPCALLBACK_NEWMAP")
end

-- ---- the cache shape this re-arms ------------------------------------------
-- BILLS_HOUSE (maps/BillsFamilysHouse.asm): the script head refuses while
-- event 0 is set, and every stone branch ends `setevent 800+n / setevent 0`.
-- With flag 0 dying on the reload above, leaving and re-entering the house
-- takes the head past its refusal to the next stone.
local cache = os.getenv("GOLD_CACHE")
if not cache then
  local home = os.getenv("HOME") or ""
  cache = home .. "/Library/Application Support/LOVE/gold-dev/gold"
end
local chunk = loadfile(cache .. "/data/generated/scripts.lua")
if not chunk then
  check(true, "gold cache absent (SKIP Bill's-house shape)")
  S.finish()
  return
end
local scripts = chunk()

local head = scripts["54:547c"]
check(type(head) == "table", "the grandpa's script head extracted")
if type(head) == "table" then
  eq(head[3] and head[3].op, "checkevent", "row 3 is a checkevent")
  eq(head[3] and head[3].event, 0, "over temporary flag 0")
  eq(head[4] and head[4].op, "iftrue", "and iftrue is the refusal branch")
end
for n, key in ipairs({ "54:557f", "54:5596", "54:55ad", "54:55c4" }) do
  local rows = scripts[key]
  local latch, story
  for _, row in ipairs(rows or {}) do
    if row.op == "setevent" and row.event == 0 then latch = true end
    if row.op == "setevent" and row.event == 799 + n then story = true end
  end
  check(story, ("stone branch %d marks its stone given (%d)"):format(n, 799 + n))
  check(latch, ("and latches temporary flag 0 (%s)"):format(key))
end

S.finish()
