
package.loaded.warpdriveCommons = nil
local w = require("warpdriveCommons")

local data

----------- Transporter room support

local transporter

function transporter_read(parData)
  data = parData
end

function transporter_name(parName)
  if transporter == nil or transporter.isInterfaced() == nil then
    return ''
  end
  return transporter.name(parName)
end

function transporter_boot()
  if transporter ~= nil then
    w.writeLn("Booting Transporter...")
    local  _, _, _, _, _ = transporter.state()
  end
end

function transporter_key(character, keycode)
  if character == 's' or character == 'S' then -- S
    transporter_start()
    return true
  elseif character == 'p' or character == 'P' then -- P
    transporter_stop()
    return true
  elseif character == 'l' or character == 'L' then -- L
    transporter_lock()
    return true
  elseif character == 'e' or character == 'E' then -- E
    transporter_energize()
    return true
  elseif character == '-' then -- -
    local energyFactor = transporter.energyFactor()
    transporter.energyFactor(energyFactor - 0.2)
    return true
  elseif character == '+' then -- +
    local energyFactor = transporter.energyFactor()
    transporter.energyFactor(energyFactor + 0.2)
    return true
  elseif character == 'c' or character == 'C' then -- C
    transporter_config()
    return true
  end
  return false
end

function transporter_page()
  w.page_begin(w.data_getName() .. " - Transporter room controls")
  
  w.setCursorPos(1, 2)
  if transporter == nil or transporter.isInterfaced() == nil then
    w.setColorDisabled()
    w.write("Transporter core not detected")
  else
    w.setCursorPos(1, 2)
    w.setColorDisabled()
    local _, signature = transporter.name()
    if (signature ~= nil) then
      w.writeCentered(2, "Signature is " .. signature)
    end
    
    w.setCursorPos(1, 3)
    w.setColorNormal()
    w.write("Beam frequency  = ")
    local beamFrequency = transporter.beamFrequency()
    w.write(w.format_integer(beamFrequency, 6))
    
    w.setCursorPos(1, 4)
    w.setColorNormal()
    w.write("Remote location = ")
    local remoteLocation = { transporter.remoteLocation() }
    if remoteLocation[3] ~= nil then
      w.write(w.format_integer(remoteLocation[1]) .. ", " .. w.format_integer(remoteLocation[2]) .. ", " .. w.format_integer(remoteLocation[3]))
    elseif remoteLocation[1] ~= nil then
      w.write(remoteLocation[1])
    else
      w.write("-not defined-")
    end
    
    w.setCursorPos(1, 6)
    w.setColorNormal()
    local energyFactor_PC = transporter.energyFactor() * 100
    w.write("Energy factor   = " .. w.format_float(math.floor(energyFactor_PC * 10) / 10, 6) .. " %")
    
    w.setCursorPos(1, 7)
    w.setColorNormal()
    w.write("Energy required = ")
    local energyStored, energyMax, energyUnits = transporter.getEnergyStatus()
    local success, energyAcquiring, energyEnergizing = transporter.getEnergyRequired()
    if success then
      w.write(w.format_integer(energyAcquiring) .. " " .. energyUnits .. "/t then " .. w.format_integer(energyEnergizing) .. " " .. energyUnits .. "/t")
    else
      w.write("???")
    end
    
    w.setCursorPos(1, 8)
    w.setColorNormal()
    w.write("Energy stored   = ")
    transporter_page_writeEnergy(energyStored, energyMax, energyUnits)
    
    w.setCursorPos(1, 9)
    w.setColorNormal()
    w.write("  -----------------------------------------------")
    
    w.setCursorPos(1, 10)
    w.setColorNormal()
    w.write("Room is ")
    local isEnabled = transporter.enable()
    if isEnabled then w.setColorSuccess() else w.setColorNormal() end
    w.write(w.format_boolean(isEnabled, "enabled", "disabled"))
    w.setColorNormal()
    w.write(".")
    
    w.setCursorPos(28, 10)
    w.setColorNormal()
    w.write("Locking is ")
    local isLockRequested = transporter.lock()
    if isLockRequested then w.setColorSuccess() else w.setColorNormal() end
    w.write(w.format_boolean(isLockRequested, "requested", "on hold"))
    w.setColorNormal()
    w.write(".")
    
    w.setCursorPos(1, 11)
    w.setColorNormal()
    w.write("Lock strength is ")
    local lockStrength = transporter.getLockStrength()
    transporter_page_writeLockStrength(lockStrength)
    
    w.setCursorPos(28, 11)
    w.setColorNormal()
    w.write("Energize is ")
    local isEnergizeRequested = transporter.energize()
    if isEnergizeRequested then w.setColorSuccess() else w.setColorNormal() end
    w.write(w.format_boolean(isEnergizeRequested, "requested", "on hold"))
    w.setColorNormal()
    w.write(".")
    
    w.setCursorPos(1, 13)
    w.setColorNormal()
    w.write("Status is ")
    local _, state, _, _, isJammed = transporter.state()
    if isJammed then
      w.setColorBad()
    end
    w.writeMultiLine(state)
    w.setColorNormal()
    w.write(".")
  end
  
  w.setCursorPos(1, 20)
  w.setColorControl()
  w.writeFullLine(" Start/stoP transporter (S/P), Configuration (C)")
  w.writeFullLine(" Lock (L), Energize (E), Energy factor (+/-)")
end

function transporter_page_writeEnergy(energyStored, energyMax, energyUnits)
  w.setCursorPos(19, 8)
  w.setColorNormal()
  w.write(w.format_integer(energyStored, 8) .. " / " .. energyMax .. " " .. energyUnits .. "  ")
end

function transporter_page_writeLockStrength(lockStrength)
  w.setCursorPos(18, 11)
  if lockStrength > 0.01 then
    local percent = math.floor(lockStrength * 1000) / 10
    if percent >= 80.0 then
      w.setColorSuccess()
    else
      w.setColorWarning()
    end
    w.write(w.format_float(percent) .. " %")
  else
    w.setColorDisabled()
    w.write("-none-")
  end
  w.setColorNormal()
  w.write(".  ")
end

function transporter_setEnergyFactor()
  if transporter ~= nil then
    data.transporter_energyFactor = transporter.energyFactor(data.transporter_energyFactor)
  end
end

function transporter_start()
  if transporter ~= nil then
    transporter.enable(true)
  end
end

function transporter_stop()
  if transporter ~= nil then
    transporter.enable(false)
  end
end

function transporter_lock()
  if transporter ~= nil then
    transporter.lock(not transporter.lock())
  end
end

function transporter_energize()
  if transporter ~= nil then
    transporter.energize(not transporter.energize())
  end
end

local transporter_configPageLoaded = false
function transporter_pulse(actual)
  local lockStrength = actual
  if transporter == nil or transporter.isInterfaced() == nil then
    w.reboot()
  end
  if w.page_getCallbackDisplay() == transporter_page and (not transporter_configPageLoaded) then
    transporter_page_writeLockStrength(lockStrength)
  
    local energyStored, energyMax, energyUnits = transporter.getEnergyStatus()
    transporter_page_writeEnergy(energyStored, energyMax, energyUnits)
  end
end

function transporter_config()
  transporter_configPageLoaded = true
  w.page_begin(w.data_getName() .. " - Transporter room configuration")
  
  w.setCursorPos(1, 2)
  if transporter == nil or transporter.isInterfaced() == nil then
    w.setColorDisabled()
    w.write("Transporter core not detected")
  else
    
    w.setCursorPos(1, 6)
    w.setColorHelp()
    w.writeFullLine(" Enter a number between 100 and 1000 %.")
    
    w.setCursorPos(1, 4)
    w.setColorNormal()
    local energyFactor_PC = transporter.energyFactor() * 100
    w.write("Energy factor (" .. math.floor(energyFactor_PC * 10) / 10 .. " %): ")
    energyFactor_PC = w.input_readInteger(energyFactor_PC)
    energyFactor_PC = transporter.energyFactor(energyFactor_PC / 100) * 100
    w.setCursorPos(1, 5)
    w.writeLn("Energy factor set to " .. math.floor(energyFactor_PC * 10) / 10 .. " %")
    w.writeFullLine(" ")
    
    w.setCursorPos(1, 7)
    w.setColorNormal()
    local remoteLocation = { transporter.remoteLocation() }
    local remoteLocation_default = "-"
    if remoteLocation[3] ~= nil then
      w.write("Remote location is currently set to " .. w.format_integer(remoteLocation[1]) .. ", " .. w.format_integer(remoteLocation[2]) .. ", " .. w.format_integer(remoteLocation[3]))
    elseif remoteLocation[1] ~= nil then
      w.write("Remote location is currently set to ")
      w.write(remoteLocation[1])
      remoteLocation_default = remoteLocation[1]
    else
      w.write("Remote location is currently undefined")
      remoteLocation[1] = "???"
    end
    
    w.setCursorPos(1, 13)
    w.setColorHelp()
    w.writeFullLine(" Enter - as player name to use coordinates.")
    w.writeFullLine(" Press Enter to save your selection.")
    
    w.setCursorPos(1, 10)
    w.setColorNormal()
    w.write("Signature, player name or dash: ")
    w.setCursorPos(1, 11)
    local remoteLocation_new = w.input_readText(remoteLocation_default)
    
    w.setCursorPos(1, 13)
    w.setColorNormal()
    w.writeFullLine(" ")
    w.writeFullLine(" ")
    
    if remoteLocation_new ~= "-" then
      remoteLocation = { transporter.remoteLocation(remoteLocation_new) }
    else
      if #remoteLocation == 1 then
        remoteLocation[1], remoteLocation[2], remoteLocation[3] = transporter.getLocalPosition()
      end
      
      w.setCursorPos(1, 10)
      w.setColorNormal()
      w.writeFullLine(" ")
      w.writeFullLine(" ")
      
      -- X
      w.setCursorPos(1, 12)
      w.setColorHelp()
      w.writeFullLine(" Enter absolute X coordinate.")
      
      w.setCursorPos(1, 10)
      w.setColorNormal()
      w.write("Remote location X coordinate (" .. w.format_integer(remoteLocation[1]) .. "): ")
      remoteLocation[1] = w.input_readInteger(remoteLocation[1])
      
      w.setCursorPos(1, 12)
      w.setColorNormal()
      w.writeFullLine(" ")
      
      -- Y
      w.setCursorPos(1, 13)
      w.setColorHelp()
      w.writeFullLine(" Enter Y < 0 to target below planet.")
      w.writeFullLine(" Enter Y > 256 to target space above.")
      
      w.setCursorPos(1, 11)
      w.setColorNormal()
      w.write("Remote location Y coordinate (" .. w.format_integer(remoteLocation[2]) .. "): ")
      remoteLocation[2] = w.input_readInteger(remoteLocation[2])
      
      w.setCursorPos(1, 13)
      w.setColorNormal()
      w.writeFullLine(" ")
      w.writeFullLine(" ")
      
      -- Z
      w.setCursorPos(1, 14)
      w.setColorHelp()
      w.writeFullLine(" Enter absolute Z coordinate.")
      
      w.setCursorPos(1, 12)
      w.setColorNormal()
      w.write("Remote location Z coordinate (" .. w.format_integer(remoteLocation[3]) .. "): ")
      remoteLocation[3] = w.input_readInteger(remoteLocation[3])
      
      w.setCursorPos(1, 14)
      w.setColorNormal()
      w.writeFullLine(" ")
      
      remoteLocation = { transporter.remoteLocation(remoteLocation[1], remoteLocation[2], remoteLocation[3]) }
    end
    
    w.setCursorPos(1, 12)
    if remoteLocation[3] ~= nil then
      w.write("Remote location updated to " .. w.format_integer(remoteLocation[1]) .. ", " .. w.format_integer(remoteLocation[2]) .. ", " .. w.format_integer(remoteLocation[3]))
    elseif remoteLocation[1] ~= nil then
      w.write("Remote location updated to " .. remoteLocation[1])
    else
      w.write("Remote location updated to invalid (?)")
    end
  end
  transporter_configPageLoaded = false
end

function transporter_register()
  w.device_register("warpdriveTransporterCore",
      function(deviceType, address, wrap) transporter = wrap end,
      function() end)
  w.event_register("transporterPulse"     , function(eventName, param) transporter_pulse(param)                                               return false end )
  w.event_register("transporterEnergizing", function(eventName, param) w.status_showWarning("Transporting "          .. param .. " entities") return false end )
  w.event_register("transporterSuccess"   , function(eventName, param) w.status_showWarning("Transported "           .. param) return false end )
  w.event_register("transporterFailure"   , function(eventName, param) w.status_showWarning("Failed transportation " .. param) return false end )
  w.data_register("transporter", transporter_read, nil, transporter_name)
end

----------- connections status

function connections_key(character, keycode)
  if character == 'n' or character == 'N' then -- N
    w.data_setName()
    return true
  end
  return false
end

function connections_page(isBooting)
  w.page_begin(w.data_getName() .. " - Connections")
  
  w.writeLn("")
  
  if transporter == nil or transporter.isInterfaced() == nil then
    w.setColorDisabled()
    w.writeLn("No Transporter core detected")
  else
    w.setColorSuccess()
    w.writeLn("Transporter core detected")
    if isBooting then
      transporter_boot()
    end
  end
  
  w.writeLn("")
  w.setColorNormal()
  w.writeLn("This is a keyboard controlled user interface.")
  w.write("Key controls are written like so: ")
  w.setColorControl()
  w.write("Action (key)")
  w.setColorNormal()
  w.writeLn(".")
  w.write("For example, typing ")
  w.setColorControl()
  w.write(" 1 ")
  w.setColorNormal()
  w.writeLn(" will open Transporter room controls.")
  
  w.setCursorPos(1, 21)
  w.setColorControl()
  w.writeFullLine(" Change computer Name (N)")
end

----------- Boot sequence

w.page_setEndText(" Home (0), Transporter room (1)")
w.page_register('0', connections_page, connections_key)
w.page_register('1', transporter_page, transporter_key)
transporter_register()

w.boot()
local success, message = pcall(w.run)
if not success then
  print("failed with message")
  print(message)
  w.sleep(3.0)
  print("rebooting...")
  w.reboot()
else
  w.close()
end
