-- FF_STORY_COMPUTER_GUARD
local function ff_story_computer_allowed()
  local label = os.getComputerLabel and os.getComputerLabel() or nil
  return fs.exists(".ff_story_computer")
    or fs.exists(".ff_titan_computer")
    or fs.exists(".ff_titan_program_id")
    or fs.exists(".ff_titan_allow_autoinstall")
    or fs.exists(".ff_titan_allow_autorun")
    or (label ~= nil and string.sub(string.lower(label), 1, 9) == "ff_titan:")
end

if not ff_story_computer_allowed() then
  return
end
local REFRESH = 8.0

local function findDisplay()
  local mon = peripheral.find("monitor")
  if mon then
    mon.setTextScale(0.5)
    return mon
  end
  return term.current()
end

local display = findDisplay()

local function useDisplay()
  term.redirect(display)
end

local function color(c)
  if term.isColor and term.isColor() then
    term.setTextColor(c)
  end
end

local function bg(c)
  if term.isColor and term.isColor() then
    term.setBackgroundColor(c)
  end
end

local function clear()
  useDisplay()
  bg(colors.black)
  term.clear()
  term.setCursorPos(1, 1)
end

local function size()
  return term.getSize()
end

local function at(x, y, text, col)
  term.setCursorPos(x, y)
  color(col or colors.white)
  write(text)
end

local function center(y, text, col)
  local w = size()
  local x = math.floor((w - #text) / 2) + 1
  if x < 1 then x = 1 end
  at(x, y, text, col)
end

local function hline(y, col)
  local w = size()
  at(1, y, string.rep("-", w), col or colors.gray)
end

local function bar(x, y, label, pct, width, col)
  if pct < 0 then pct = 0 end
  if pct > 100 then pct = 100 end

  local filled = math.floor((pct / 100) * width)
  local empty = width - filled

  at(x, y, label, colors.gray)
  at(x + 18, y, "[", colors.darkGray)
  at(x + 19, y, string.rep("#", filled), col)
  at(x + 19 + filled, y, string.rep(".", empty), colors.gray)
  at(x + 19 + width, y, "]", colors.darkGray)

  local p = tostring(pct) .. "%"
  at(x + 22 + width, y, p, col)
end

local function smallBox(x, y, w, h, title, col)
  at(x, y, "+" .. string.rep("-", w - 2) .. "+", col)
  for i = 1, h - 2 do
    at(x, y + i, "|", col)
    at(x + w - 1, y + i, "|", col)
  end
  at(x, y + h - 1, "+" .. string.rep("-", w - 2) .. "+", col)
  at(x + 2, y, " " .. title .. " ", col)
end

local logs = {
  "13:02  GREEN.ROUTE    elevator accepted surface descent",
  "13:08  DECON          shower three failed pressure check",
  "13:11  BOTANY         spore tray moved four centimeters",
  "13:17  SECURITY       holding cells sealed by local relay",
  "13:22  PRESSURE       valve hall reports stale gauge data",
  "13:24  RECEPTION      unauthorized access",
  "13:28  COOLANT        pump room vents clogged",
  "13:31  QUARANTINE     sample freezers and botany escape",
  "13:36  ARCHIVE        red route memo viewed locally",
  "13:41  LOBBY          lower access gate still hard locked",
  "13:44  BOTANY         growth map disagrees with floor plan?",
  "13:49  SECURITY       badge reader returned old staff id",
  "13:53  ELEVATOR       lower contact absent",
  "13:57  PRESSURE       override waiting on manual proof"
}

local function drawPageA(tick)
  clear()
  local w, h = size()

  center(1, "NEMESIS LOCKDOWN", colors.red)
  center(2, "TITAN / GREEN SECTOR / MIDDLE FACILITY", colors.gray)
  hline(3, colors.red)

  local integrity = 78 - (tick % 4)
  local quarantine = 61 + (tick % 5)
  local pressure = 84 - (tick % 3)
  local route = 22 + (tick % 8)

  at(2, 5, "FACILITY INTEGRITY", colors.red)
  at(26, 5, tostring(integrity) .. "%", colors.white)

  at(2, 6, "FRAGMNENT", colors.lime)
  at(26, 6, "SECURE", colors.lime)

  at(2, 7, "EXTERNAL PRESSURE", colors.red)
  at(26, 7, "240 o", colors.white)

  at(2, 8, "CONTAINMENT STATUS", colors.red)
  at(26, 8, "RAGNAROK", colors.red)

  at(2, 10, "\"EXPENDABLE\" PROTOCOL", colors.red)
  at(2, 11, "IN PROCESS", colors.red)

  bar(2, 13, "Pressure", pressure, 18, colors.lime)
  bar(2, 14, "Quarantine", quarantine, 18, colors.orange)
  bar(2, 15, "Route Lock", route, 18, colors.red)
  bar(2, 16, "Cameras", 73, 18, colors.lime)

  smallBox(2, 18, 36, 8, "LOWER HULL ACCESS", colors.red)
  at(4, 20, "Pressure override       [ ]", colors.white)
  at(4, 21, "Black clearance         [ ]", colors.white)
  at(4, 22, "Quarantine release      [ ]", colors.white)
  at(4, 23, "Albedo authorization    [ ]", colors.white)
  at(4, 25, "Gate status: SEALED", colors.red)

  smallBox(41, 5, math.max(32, w - 42), 21, "CONTAINMENT LOG", colors.red)

  local start = (tick % (#logs - 9)) + 1
  for i = 0, 9 do
    local log = logs[start + i]
    local col = colors.white
    if string.find(log, "BOTANY") or string.find(log, "QUARANTINE") then col = colors.orange end
    if string.find(log, "lower") or string.find(log, "RAGNAROK") then col = colors.red end
    if string.find(log, "SECURITY") then col = colors.cyan end
    at(43, 7 + i, log, col)
  end

  at(43, 19, "PERSONNEL COUNT:", colors.gray)
  at(61, 19, "UNKNOWN", colors.red)

  at(43, 21, "ACTIVE CAMERAS:", colors.gray)
  at(61, 21, "28 / 39", colors.white)

  at(43, 22, "DECON LINE:", colors.gray)
  at(61, 22, "DIRTY", colors.orange)

  at(43, 23, "ELEVATOR:", colors.gray)
  at(61, 23, "GREEN ONLY", colors.lime)

  at(43, 24, "RED ROUTE:", colors.gray)
  at(61, 24, "NOT PUBLISHED", colors.red)

  hline(h, colors.red)
end

local function drawPageB(tick)
  clear()
  local w, h = size()

  center(1, "GREEN SECTOR OPERATIONS", colors.lime)
  center(2, "LOCAL SECURITY STATUS BOARD", colors.gray)
  hline(3, colors.lime)

  smallBox(2, 5, 33, 9, "RESEARCH WING", colors.lime)
  at(4, 7, "Botany lab:        ACTIVE", colors.white)
  at(4, 8, "Sample freezer:    LOCKED", colors.orange)
  at(4, 9, "Test chambers:     DIRTY", colors.orange)
  at(4, 10, "Spore count:       18 ppm", colors.red)
  at(4, 11, "Last motion:       RECENT", colors.white)
  at(4, 12, "Note: we are all doomed", colors.red)

  smallBox(38, 5, 35, 9, "SECURITY WING", colors.cyan)
  at(40, 7, "Office:            ONLINE", colors.lime)
  at(40, 8, "Armory:            SEALED", colors.orange)
  at(40, 9, "Holding cells:     CLOSED", colors.white)
  at(40, 10, "Badge reader:      DIRTY", colors.orange)
  at(40, 11, "Black card:        UNISSUED", colors.red)
  at(40, 12, "Camera gap:      999 frames", colors.red)

  smallBox(2, 16, 33, 9, "ENGINEERING", colors.orange)
  at(4, 18, "Pump room:         LOW HUM", colors.white)
  at(4, 19, "Valve hall:        MANUAL", colors.orange)
  at(4, 20, "Coolant tunnel:    WET", colors.cyan)
  at(4, 21, "Pressure control:  LOCKED", colors.red)
  at(4, 22, "Override:          MISSING", colors.red)
  at(4, 23, "Gauge drift:       23.8%", colors.orange)

  smallBox(38, 16, 35, 9, "MAIN LOBBY", colors.lime)
  at(40, 18, "Reception:         EMPTY", colors.white)
  at(40, 19, "Decon hall:        FAILED", colors.red)
  at(40, 20, "Lower gate:        HARD LOCK", colors.red)
  at(40, 21, "Elevator:          GREEN STOP", colors.lime)
  at(40, 22, "Public route:      CLOSED", colors.orange)
  at(40, 23, "Clean zones:       DISPUTED", colors.red)

  if w > 78 then
    smallBox(77, 5, w - 78, 20, "FEED NOTES", colors.red)
    at(79, 7, "13:10  Staff route table expired", colors.white)
    at(79, 8, "13:14  [REDACTED]", colors.orange)
    at(79, 9, "13:16  No badge read logged", colors.red)
    at(79, 10, "13:22  [REDACTED]", colors.white)
    at(79, 11, "13:25  Reception camera blink", colors.white)
    at(79, 12, "13:30  Old route request replayed", colors.red)
    at(79, 13, "13:33  Decon mist smells organic", colors.orange)
    at(79, 14, "13:36  Botany weight increase", colors.red)
    at(79, 15, "13:39  Main lobby clear", colors.lime)
    at(79, 16, "13:42  Main lobby clear", colors.lime)
    at(79, 17, "13:43  Main lobby not clear", colors.red)
    at(79, 19, "Local note:", colors.gray)
    at(79, 20, "Do not trust automatic safe marks.", colors.white)
    at(79, 21, "we are all doomed.", colors.red)
  end

  hline(h, colors.lime)
end

local tick = 0

while true do
  useDisplay()
  if tick % 2 == 0 then
    drawPageA(tick)
  else
    drawPageB(tick)
  end
  tick = tick + 1
  sleep(REFRESH)
end