-- 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

local function ff_story_computer_self_clean()
  for _, path in ipairs({"startup", "startup.lua"}) do
    if fs.exists(path) and not fs.isDir(path) then
      local handle = fs.open(path, "r")
      local first_line = nil
      if handle ~= nil then
        first_line = handle.readLine()
        handle.close()
      end
      if first_line == "-- FF_STORY_COMPUTER_GUARD" then
        fs.delete(path)
      end
    end
  end
end

if not ff_story_computer_allowed() then
  ff_story_computer_self_clean()
  return
end
local OUTPUT_SIDE = "back"
local STATE_FILE = ".titan_descent_authorized"

local answers = {
  coupler = "COUPLER12",
  power = "REACTIVATE",
  route = "GREEN",
  boot = "REBOOT"
}

local function hasColor()
  return term.isColor and term.isColor()
end

local function c(col)
  if hasColor() then term.setTextColor(col) end
end

local function cls()
  term.setBackgroundColor(colors.black)
  term.clear()
  term.setCursorPos(1, 1)
end

local function writeLine(text, col)
  c(col or colors.white)
  print(text)
end

local function readClean()
  c(colors.white)
  write("> ")
  local s = read() or ""
  s = string.upper(s)
  s = string.gsub(s, "^%s+", "")
  s = string.gsub(s, "%s+$", "")
  return s
end

local function pause()
  c(colors.gray)
  print("")
  print("[key] back")
  os.pullEvent("key")
end

local function header(title)
  cls()
  c(colors.lightBlue)
  print("TITAN DESCENT CONTROL")
  c(colors.gray)
  print("LOCAL SURFACE TERMINAL")
  print("---------------------------------------")
  if title then
    c(colors.white)
    print(title)
    c(colors.gray)
    print("---------------------------------------")
  end
  c(colors.white)
end

local function authorized()
  return fs.exists(STATE_FILE)
end

local function saveAuthorized()
  local f = fs.open(STATE_FILE, "w")
  f.write("AUTHORIZED")
  f.close()
end

local function setOutput(on)
  redstone.setOutput(OUTPUT_SIDE, on)
end

local function bootRedstone()
  setOutput(authorized())
end

local function drawText(lines)
  for _, line in ipairs(lines) do
    if line == "COUPLER12" or line == "REACTIVATE" or line == "GREEN" or line == "REBOOT" then
      writeLine(line, colors.lime)
    elseif string.find(line, "WRONG") or string.find(line, "DENIED") or string.find(line, "MISSING") then
      writeLine(line, colors.red)
    elseif string.find(line, "NOTE") or string.find(line, "SHIFT") or string.find(line, "LOCAL") then
      writeLine(line, colors.orange)
    elseif string.find(line, "MIDDLE MOUSE") or string.find(line, "SCROLL WHEEL") or string.find(line, "RIGHT CLICK") then
      writeLine(line, colors.cyan)
    else
      writeLine(line, colors.white)
    end
  end
end

local function page(title, lines)
  header(title)
  drawText(lines)
  pause()
end

local function status()
  header("STATUS")

  if authorized() then
    drawText({
      "DESCENT DRIVE: ACTIVE",
      "",
      "Output is held ON.",
      "",
      "Side:",
      OUTPUT_SIDE,
      "",
      "If the gearbox is wired through pistons,",
      "it should now sit in the drive socket.",
      "",
      "If nothing moved, check the redstone side."
    })
  else
    drawText({
      "DESCENT DRIVE: LOCKED",
      "",
      "The elevator can not be routed yet.",
      "",
      "Open the local files.",
      "Run AUTH when ready."
    })
  end

  pause()
end

local function fileCoupler()
  page("FILE: COUPLER", {
    "MAINTENANCE TAG",
    "",
    "Drive socket is empty.",
    "",
    "The missing part was pulled after G-12.",
    "Nobody wrote the full reason.",
    "",
    "Storage label on the old crate:",
    "",
    "COUPLER12",
    "",
    "Do not rename it.",
    "Daan already tried."
  })
end

local function filePower()
  page("FILE: MOTOR", {
    "SHIFT NOTE",
    "",
    "Motor line is locked out.",
    "",
    "Surface grid tripped twice last week.",
    "Both trips happened after the elevator",
    "arrived without a call.",
    "",
    "Reset word on the breaker label:",
    "",
    "REACTIVATE",
    "",
    "Use caps if typing into old terminals..."
  })
end

local function fileRoute()
  page("FILE: ROUTE", {
    "LOCAL ROUTE MEMO",
    "",
    "Surface may only send the elevator",
    "to the first lower stop.",
    "",
    "Red routing is blocked from here.",
    "",
    "Approved route word:",
    "",
    "GREEN",
    "",
    "Do not try red from surface.",
    "Only recently was it published to us."
  })
end

local function fileBoot()
  page("FILE: BOOT", {
    "CONTROL ROOM PAPER NOTE",
    "",
    "If descent panel stays frozen:",
    "",
    "type the boot word",
    "wait for the brake light",
    "then select the floor manually",
    "",
    "Boot word:",
    "",
    "REBOOT",
    "",
    "This is a workaround."
  })
end

local function fileUseElevator()
  page("FILE: FLOOR SELECT", {
    "ELEVATOR USE NOTE",
    "",
    "The floor button is not a normal button.",
    "",
    "Look at the elevator control.",
    "",
    "Use MIDDLE MOUSE BUTTON",
    "or SCROLL WHEEL",
    "to select the floor.",
    "",
    "Then RIGHT CLICK.",
    "",
    "Yes, this should be printed on the wall.",
    "No, it was not printed on the wall. lol"
  })
end

local function fileG12()
  page("FILE: G-12", {
    "SECURITY SUMMARY",
    "",
    "The cage came back empty.",
    "",
    "Boot marks were on the ceiling.",
    "There was an awful odor in it too.",
    "The elevator shaft needs to be cleaned.",
    "How is mycelium growing so deep?"
  })
end

local function fileDaan()
  page("FILE: DAAN", {
    "UNSENT MESSAGE",
    "",
    "Mira,",
    "",
    "I took the coupler out.",
    "",
    "If they ask, say it was wear.",
    "",
    "The cage started arriving early.",
    "Not late. Early.",
    "",
    "I heard the call bell before I pressed it."
  })
end

local function fileLocal()
  page("FILE: LOCAL ONLY", {
    "SYSTEM NOTICE",
    "",
    "This terminal is not linked",
    "to the Titan database.",
    "",
    "Local files only.",
    "Old surface cache only.",
    "",
    "Do not expect live answers.",
    "",
    "If a live answer appears here,",
    "unplug the terminal.",
    "",
    "If it keeps typing, leave."
  })
end

local function successScreen()
  header("AUTHORIZED")

  drawText({
    "ALL WORDS ACCEPTED",
    "",
    "Coupler check: OK",
    "Motor reset: OK",
    "Route lock: OK",
    "Panel boot: OK",
    "",
    "Output now held ON.",
    "",
    "DESCENT DRIVE READY",
    "",
    "Select GREEN on the elevator control.",
    "Use scroll wheel or middle mouse.",
    "Right click to confirm."
  })

  pause()
end

local function failScreen(label, got)
  header("DENIED")

  drawText({
    "CHECK FAILED",
    "",
    "Field:",
    label,
    "",
    "Input:",
    got,
    "",
    "Result:",
    "WRONG",
    "",
    "Open the matching local file.",
    "The word is printed by itself."
  })

  pause()
end

local function ask(label, expected)
  header("AUTH / " .. label)

  drawText({
    "Enter one word.",
    "",
    "No spaces and all caps.",
    "",
    "Required field:",
    label,
    ""
  })

  local got = readClean()

  if got == expected then
    c(colors.lime)
    print("")
    print("CORRECT")
    sleep(0.8)
    return true
  end

  c(colors.red)
  print("")
  print("INCORRECT")
  sleep(0.8)
  failScreen(label, got)
  return false
end

local function auth()
  if authorized() then
    page("AUTH", {
      "Already authorized.",
      "",
      "Output is still ON.",
      "",
      "If the machine is not moving,",
      "the problem is wiring."
    })
    return
  end

  if not ask("COUPLER", answers.coupler) then return end
  if not ask("MOTOR", answers.power) then return end
  if not ask("ROUTE", answers.route) then return end
  if not ask("PANEL", answers.boot) then return end

  saveAuthorized()
  setOutput(true)
  successScreen()
end

local function debug()
  header("SERVICE PANEL")

  drawText({
    "Local service controls.",
    "",
    "RESET clears saved authorization.",
    "ON forces output on.",
    "OFF forces output off.",
    "",
    "Type command."
  })

  local got = readClean()

  if got == "RESET" then
    if fs.exists(STATE_FILE) then fs.delete(STATE_FILE) end
    setOutput(false)
    page("SERVICE PANEL", { "Access state cleared.", "", "Output OFF." })
  elseif got == "ON" then
    setOutput(true)
    page("SERVICE PANEL", { "Signal override ON.", "", "Saved state unchanged." })
  elseif got == "OFF" then
    setOutput(false)
    page("SERVICE PANEL", { "Signal override OFF.", "", "Saved state unchanged." })
  else
    page("SERVICE PANEL", { "No change." })
  end
end

bootRedstone()

while true do
  header()

  if authorized() then
    writeLine("DESCENT DRIVE: ACTIVE", colors.lime)
  else
    writeLine("DESCENT DRIVE: LOCKED", colors.red)
  end

  print("")
  writeLine("1. Status")
  writeLine("2. Coupler file")
  writeLine("3. Motor file")
  writeLine("4. Route file")
  writeLine("5. Boot file")
  writeLine("6. Elevator use")
  writeLine("7. Incident G-12")
  writeLine("8. Daan message")
  writeLine("9. Local-only notice")
  writeLine("A. AUTH")
  writeLine("D. Service")
  writeLine("Q. Close")

  print("")
  local input = readClean()

  if input == "Q" or input == "QUIT" or input == "EXIT" then
    cls()
    writeLine("SESSION CLOSED", colors.gray)
    return
  elseif input == "1" then
    status()
  elseif input == "2" then
    fileCoupler()
  elseif input == "3" then
    filePower()
  elseif input == "4" then
    fileRoute()
  elseif input == "5" then
    fileBoot()
  elseif input == "6" then
    fileUseElevator()
  elseif input == "7" then
    fileG12()
  elseif input == "8" then
    fileDaan()
  elseif input == "9" then
    fileLocal()
  elseif input == "A" or input == "AUTH" then
    auth()
  elseif input == "D" or input == "SERVICE" then
    debug()
  else
    c(colors.red)
    print("Invalid.")
    sleep(0.7)
  end
end