-- factoryos.programs.macrocon — configurable shortcut console.
-- Reads /factoryos/macros.cfg: return { {label, action, params, confirm}, ... }
-- Buttons send "core.ui"/"macro". confirm=true entries need two taps.

local sched  = require("factoryos.core.sched")
local config = require("factoryos.core.config")
local util   = require("factoryos.util")
local Node   = require("factoryos.net.node")

local cfg    = config.loadOr("/factoryos/node.cfg", {})
local macros = config.load("/factoryos/macros.cfg") or {
  { label = "POWER GRID", action = "ui.open_app", params = { app = "power" } },
  { label = "NETWORK",    action = "ui.open_app", params = { app = "nodes" } },
  { label = "DESKTOP",    action = "ui.home" },
}

local node = Node.new(cfg)
assert(node:open(), "macrocon: no modem")

local t = peripheral.find("monitor") or term
if t.setTextScale then pcall(t.setTextScale, 0.5) end
local w, h = t.getSize()

local armed = nil        -- index armed for confirm
local armedAt = 0
local status = ""

local function draw()
  t.setBackgroundColor(colors.black)
  t.setTextColor(colors.white)
  t.clear()
  for i, m in ipairs(macros) do
    if i > h - 1 then break end
    local label = m.label
    if armed == i then
      label = "> " .. label .. " ?"
      t.setTextColor(colors.yellow)
    else
      label = "  " .. label
      t.setTextColor(colors.white)
    end
    t.setCursorPos(1, i)
    t.write(label:sub(1, w))
  end
  t.setTextColor(colors.lightGray)
  t.setCursorPos(1, h)
  t.write(status:sub(1, w))
end

local function fire(m)
  node:spawn(function()
    local ok, res = node:call("core.ui", "macro",
      { action = m.action, params = m.params },
      { timeout = 2, chan = node.chan.ui, auth = cfg.token })
    status = ok and (m.label .. " ok") or (m.label .. " FAIL " ..
      tostring(res and res.err or res or ""))
    draw()
  end, "macro.send")
end

local function press(i)
  local m = macros[i]
  if not m then return end
  if m.confirm then
    if armed == i and (util.clock() - armedAt) < 5 then
      armed = nil; fire(m)
    else
      armed, armedAt = i, util.clock()
      status = m.label .. ": tap again to confirm"
    end
  else
    fire(m)
  end
  draw()
end

node:on("monitor_touch", function(_, _, y) press(y) end)
node:on("mouse_click", function(_, _, y) press(y) end)
node:on("char", function(c)
  local i = tonumber(c)
  if i and macros[i] then press(i) end
end)

draw()
node:run()
