-- 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
-- TITAN SURFACE DESCENT TERMINAL
-- NODE: SURFACE ELEVATOR REAUTHORIZATION
-- SAVE AS: startup
--
-- Import:
-- pastebin get PASTE_CODE startup
-- reboot
--
-- Output:
-- Redstone signal stays ON after puzzle completion.
-- Put redstone behind the computer by default.

local OUTPUT_SIDE = "back"
local STATE_FILE = ".descent_reauthorized"

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

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

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

local function header(name)
  cls()
  color(colors.lightBlue)
  print("TITAN DESCENT CONTROL")
  color(colors.gray)
  print("LOCAL CACHE / SURFACE NODE")
  print("---------------------------------------")
  if name then
    color(colors.white)
    print(name)
    color(colors.gray)
    print("---------------------------------------")
  end
  color(colors.white)
end

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

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

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

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

local function boot()
  output(armed())
end

local function readLower()
  color(colors.gray)
  write("> ")
  color(colors.white)
  return string.upper(read() or "")
end

local function result(ok)
  if ok then
    color(colors.lime)
    print("")
    print("CORRECT")
  else
    color(colors.red)
    print("")
    print("INCORRECT")
  end
  sleep(0.9)
end

local function showLines(title, lines)
  header(title)
  for _, v in ipairs(lines) do
    if v:find("%[.-%]") then
      color(colors.orange)
    elseif v:find("MIDDLE MOUSE") or v:find("SCROLL WHEEL") or v:find("RIGHT CLICK") then
      color(colors.lime)
    elseif v:find("RED") or v:find("LOWER") or v:find("G%-12") then
      color(colors.red)
    else
      color(colors.white)
    end
    print(v)
  end
  waitKey()
end

local files = {
  {
    title = "FILE 01 / SOCKET",
    lines = {
      "The drive socket is empty.",
      "",
      "No damage around the teeth.",
      "No burn marks on the motor line.",
      "",
      "Someone removed the part cleanly.",
      "",
      "Label on the empty crate:",
      "",
      "[GEARBOX]",
      "",
      "The handwriting is Daan's.",
      "The shake is not."
    }
  },
  {
    title = "FILE 02 / G-12",
    lines = {
      "Incident G-12.",
      "",
      "The cage came up by itself.",
      "",
      "Floor dry.",
      "Walls clean.",
      "",
      "Prints above the lamp housing.",
      "",
      "Report uses one word twice:",
      "",
      "[CEILING]",
      "",
      "The second use is underlined."
    }
  },
  {
    title = "FILE 03 / ROUTE",
    lines = {
      "Surface routing is limited.",
      "",
      "The lower call was removed",
      "after the voice test.",
      "",
      "Surface may only send the cage",
      "to the middle facility.",
      "",
      "Old maps call that stop:",
      "",
      "[GREEN]",
      "",
      "No other surface route is valid."
    }
  },
  {
    title = "FILE 04 / LOCAL",
    lines = {
      "Local systems outlived staff.",
      "",
      "Door cache alive.",
      "Brake cache alive.",
      "Route cache alive.",
      "",
      "The database is cut off.",
      "",
      "The local word remains:",
      "",
      "[AWAKE]",
      "",
      "Do not sync with main archive."
    }
  },
  {
    title = "FILE 05 / BUTTON",
    lines = {
      "ELEVATOR USE NOTE",
      "",
      "The elevator button does not",
      "open a normal menu.",
      "",
      "Use MIDDLE MOUSE BUTTON",
      "or SCROLL WHEEL to select floor.",
      "",
      "Then RIGHT CLICK the button.",
      "",
      "If nothing moves, check the",
      "floor selection first.",
      "",
      "Yes, this note is ugly.",
      "It saved arguments."
    }
  }
}

local function status()
  header("STATUS")

  if armed() then
    color(colors.lime)
    print("DESCENT DRIVE: AUTHORIZED")
    color(colors.white)
    print("")
    print("Redstone output is active.")
    print("Side: " .. OUTPUT_SIDE)
    print("")
    print("Use the elevator button.")
    print("Scroll to GREEN.")
    print("Right click.")
  else
    color(colors.orange)
    print("DESCENT DRIVE: LOCKED")
    color(colors.white)
    print("")
    print("Read the local files.")
    print("Run reauthorization.")
    print("")
    print("Answers are one word.")
  end

  waitKey()
end

local function ask(label, answer)
  header(label)
  print("Type the marked word.")
  print("")
  local input = readLower()
  local ok = input == answer
  result(ok)
  return ok
end

local function reauthorize()
  if armed() then
    header("REAUTHORIZATION")
    color(colors.lime)
    print("Already authorized.")
    waitKey()
    return
  end

  header("REAUTHORIZATION")
  print("Surface descent requires")
  print("four local confirmations.")
  print("")
  print("Answers are one word.")
  print("Local files contain them.")
  waitKey()

  if not ask("CHECK 01 / SOCKET", "GEARBOX") then return end
  if not ask("CHECK 02 / G-12", "CEILING") then return end
  if not ask("CHECK 03 / ROUTE", "GREEN") then return end
  if not ask("CHECK 04 / LOCAL", "AWAKE") then return end

  header("COUPLING")
  color(colors.gray)
  print("Writing local state...")
  sleep(0.8)
  print("Holding output...")
  sleep(0.8)
  print("Signal side: " .. OUTPUT_SIDE)
  sleep(0.8)

  saveArmed()
  output(true)

  color(colors.lime)
  print("")
  print("AUTHORIZED")
  color(colors.white)
  print("")
  print("Drive socket may now engage.")
  print("")
  print("Select GREEN with scroll wheel.")
  print("Right click elevator button.")

  waitKey()
end

local function debug()
  header("SERVICE PANEL")
  print("RESET clears authorization.")
  print("ON forces output.")
  print("OFF drops output.")
  print("")
  local input = readLower()

  if input == "RESET" then
    if fs.exists(STATE_FILE) then fs.delete(STATE_FILE) end
    output(false)
    color(colors.orange)
    print("")
    print("RESET")
    sleep(0.8)
  elseif input == "ON" then
    output(true)
    color(colors.lime)
    print("")
    print("ON")
    sleep(0.8)
  elseif input == "OFF" then
    output(false)
    color(colors.orange)
    print("")
    print("OFF")
    sleep(0.8)
  else
    color(colors.red)
    print("")
    print("NO CHANGE")
    sleep(0.8)
  end
end

boot()

while true do
  header()

  if armed() then
    color(colors.lime)
    print("DRIVE: AUTHORIZED")
  else
    color(colors.orange)
    print("DRIVE: LOCKED")
  end

  color(colors.white)
  print("")
  print("1. status")
  print("2. file 01 / socket")
  print("3. file 02 / G-12")
  print("4. file 03 / route")
  print("5. file 04 / local")
  print("6. file 05 / button")
  print("7. reauthorize")
  print("8. debug")
  print("")
  print("Q. close")

  local input = string.lower(readLower())

  if input == "q" or input == "quit" or input == "exit" then
    cls()
    color(colors.gray)
    print("SESSION CLOSED")
    return
  elseif input == "1" then
    status()
  elseif input == "2" then
    showLines(files[1].title, files[1].lines)
  elseif input == "3" then
    showLines(files[2].title, files[2].lines)
  elseif input == "4" then
    showLines(files[3].title, files[3].lines)
  elseif input == "5" then
    showLines(files[4].title, files[4].lines)
  elseif input == "6" then
    showLines(files[5].title, files[5].lines)
  elseif input == "7" then
    reauthorize()
  elseif input == "8" then
    debug()
  else
    color(colors.red)
    print("Invalid.")
    sleep(0.6)
  end
end