-- Launcher Delete affordance (src/import/RomImporter.lua): the two-click arm
-- that guards both save-slot and mod deletes (#433).  Every Delete control in
-- the FlexLove view routes through RomImporter:pressDelete, and every other
-- queued action clears self._confirmDelete (RomImporter:runActions as the
-- batch drains, #780), so the guarantees live on this seam: the first press only arms, the second
-- press on the SAME target commits, any other target or a cleared arm asks
-- again, and a stale arm expires instead of committing much later.
--   luajit tests/engine/launcher_delete_confirm.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")

-- pressDelete timestamps the arm and expires it, so the clock has to move
local clock = 1000
love.timer.getTime = function() return clock end

local RomImporter = require("src.import.RomImporter")

local function launcher()
  local self = setmetatable({}, RomImporter)
  self.deleted = {}
  return self
end

local function press(self, kind, id, version)
  return self:pressDelete(kind, id, version, function()
    table.insert(self.deleted, tostring(kind) .. "/" .. tostring(version)
      .. "/" .. tostring(id))
  end)
end

-- ------- a save Delete needs two clicks on the same row

do
  local self = launcher()
  eq(press(self, "slot", "slot1", "red"), false,
    "the first click on Delete does not delete")
  eq(#self.deleted, 0, "nothing was committed by the arm")
  check(self._confirmDelete ~= nil and self._confirmDelete.id == "slot1",
    "the first click arms that row")
  eq(press(self, "slot", "slot1", "red"), true,
    "the second click on it deletes")
  eq(self.deleted[1], "slot/red/slot1", "the commit ran for that row")
  eq(self._confirmDelete, nil, "the arm is spent")
end

-- ------- the arm is per row, per version

do
  local self = launcher()
  press(self, "slot", "slot1", "red")
  eq(press(self, "slot", "slot2", "red"), false,
    "a click on another row's Delete only arms that row")
  eq(self._confirmDelete.id, "slot2", "the arm moved to the row just clicked")

  press(self, "slot", "slot1", "red")     -- re-arm slot1
  eq(press(self, "slot", "slot1", "blue"), false,
    "an arm from one game's tab cannot fire on another")
  eq(#self.deleted, 0, "no cross-target pair ever committed")
end

-- ------- any other action press disarms (the view clears the arm)

do
  local self = launcher()
  press(self, "slot", "slot1", "red")
  self._confirmDelete = nil               -- what queueAction does on any
                                          -- non-delete action press
  eq(press(self, "slot", "slot1", "red"), false,
    "a press elsewhere disarms, so Delete asks again")
  eq(#self.deleted, 0, "and the cleared arm never committed")
end

-- ------- a stale arm expires instead of committing much later

do
  local self = launcher()
  press(self, "slot", "slot1", "red")
  clock = clock + 30
  eq(press(self, "slot", "slot1", "red"), false,
    "an arm older than the confirm window is dead")
  eq(press(self, "slot", "slot1", "red"), true,
    "and the fresh pair still deletes")
end

-- ------- mods delete arms the same way (version is nil for mods)

do
  local self = launcher()
  eq(press(self, "mod", "bigmod", nil), false,
    "the first click on a mod's Delete does not delete")
  eq(press(self, "mod", "bigmod", nil), true,
    "the second click removes the mod")
  eq(self.deleted[1], "mod/nil/bigmod", "the mod commit ran")
end

T.finish("launcher delete confirm")
