-- factoryos.apps.switches — every named redstone output in the system,
-- grouped by node. ENTER toggles. Works for plain computer sides and
-- Advanced Peripherals redstoneIntegrator ports alike.

return {
  id = "switches", name = "SWITCHES",
  desc = "Named redstone circuits",

  create = function(ctx)
    local W     = require("factoryos.ui.widgets")
    local sched = require("factoryos.core.sched")
    local util  = require("factoryos.util")
    local node, wm = ctx.node, ctx.wm
    local C = W.colors

    local list = W.ListBox({ x = 2, y = 3, w = 54, h = 13 })
    local status = W.Label({ x = 2, y = 17, w = 54, text = "", color = C.dim })

    -- find every node advertising rswitch.control, read its outputs
    local function refresh()
      node:spawn(function()
        local okR, rr = node:call("core.registry", "query")
        if not okR then status.text = "registry unreachable"; wm:draw(); return end
        local items = {}
        for _, n in pairs(rr.nodes or {}) do
          local has = false
          for _, s in ipairs(n.services or {}) do
            if s == "rswitch.control" then has = true end
          end
          if has and n.state ~= "offline" then
            local ok, res = node:call("rswitch.read", "list", nil,
              { to = n.id, timeout = 2 })
            if ok and res.outputs then
              for _, o in ipairs(res.outputs) do
                items[#items + 1] = {
                  text = string.format("%-3s %-16s %-14s %s",
                    o.state and "[x]" or "[ ]", o.name,
                    n.name or "?", o.side or ""),
                  data = { node = n.id, output = o.name },
                }
              end
            else
              items[#items + 1] = { text = string.format("    %s (no answer)",
                n.name or n.id) }
            end
          end
        end
        if #items == 0 then
          items[1] = { text = "no switch nodes found" }
        end
        list.items = items
        if list.sel > #items then list.sel = math.max(1, #items) end
        status.text = string.format("%d circuits", #items)
        wm:draw()
      end, "sw.refresh")
    end

    local function toggle(item)
      if not item.data then return end
      node:spawn(function()
        local ok, res = node:call("rswitch.control", "toggle",
          { name = item.data.output },
          { to = item.data.node, timeout = 3, auth = node.cfg.token })
        status.text = ok
          and string.format("%s -> %s", item.data.output,
            tostring(res.observed))
          or ("toggle failed: " .. tostring(res and res.err or res))
        refresh()
      end, "sw.toggle")
    end

    list.onActivate = toggle

    node:on("telemetry.updated", function() refresh() end)
    node:spawn(function()
      while true do sched.sleep(5); refresh() end
    end, "sw.poll")

    refresh()
    return {
      title = "SWITCHES", x = 3, y = 2, w = 58, h = 19,
      widgets = {
        W.Label({ x = 2, y = 2, w = 54, color = C.dim,
          text = "ST  OUTPUT           NODE           TARGET" }),
        list,
        status,
      },
    }
  end,
}
