if not term.isColor() then
  print("Advanced computer required")
  error()
end

local function showError(message)
  term.setBackgroundColor(colors.black)
  term.setTextColor(colors.red)
  term.write(message)
  term.setBackgroundColor(colors.black)
  term.setTextColor(colors.white)
  print()
end

local function showErrorAndExit(message)
  showError(message)
  error()
end

local radar
local sides = peripheral.getNames()
for _, side in pairs(sides) do
  if peripheral.getType(side) == "warpdriveRadar" then
    print("Radar found on " .. side)
    radar = peripheral.wrap(side)
  end
end
if radar == nil or radar.isInterfaced() == nil then
  showErrorAndExit("No radar detected")
end

local argv = { ... }
if #argv ~= 1 then
  showErrorAndExit("Usage: scan <scanRadius>")
end

local radius = tonumber(argv[1])

local w, h = term.getSize()
local scale = math.min(w, h) / 2
local _, _, radarX, radarY, radarZ = radar.getGlobalPosition()

term.clear()

local function colorScreen(color)
  for a = 2, w - 1 do
    for b = 1, h do
      paintutils.drawPixel(a, b, color)
    end
  end
end

local function textOut(x, y, text, fg, bg)
  term.setCursorPos(x, y)
  term.setTextColor(fg)
  term.setBackgroundColor(bg)
  term.write(text)
  local _, yt = term.getCursorPos()
  term.setCursorPos(1, yt + 1)
end

local function translateXZ(oldX, oldZ)
  local x = radarX - oldX
  local z = radarZ - oldZ
  
  x = x / (radius / scale)
  z = z / (radius / scale)
  
  x = x + (w / 2)
  z = z + (h / 2)
  
  x = math.floor(x)
  z = math.floor(z)
  
  return x, z
end

local function drawContact(x, _, z, name, color)
  local newX, newZ = translateXZ(x, z)
  
  paintutils.drawPixel(newX, newZ, color)
  textOut(newX - 3, newZ + 1, "[" .. name .. "]", colors.white, colors.black)
end

local function scanAndDraw()
  local energyStored, energyMax, _ = radar.getEnergyStatus()
  if energyStored == nil then energyStored = 0 end
  if energyMax == nil or energyMax == 0 then energyMax = 1 end
  
  radar.radius(radius)
  local success, result = radar.getEnergyRequired()
  if not success then
    showErrorAndExit(result)
  end
  local energyRequired = result
  
  if energyRequired <= 0 or energyStored < energyRequired then
    textOut((w / 2) - 7, 1, " /!\\  LOW POWER ", colors.white, colors.red)
    os.sleep(1)
    
    return 0
  end
  
  radar.start()
  local scanDuration = radar.getScanDuration()
  textOut((w / 2) - 7, 1, "   ping sent    ", colors.gray, colors.black)
  os.sleep(scanDuration)
  
  local delay = 0
  local numResults
  repeat
    numResults = radar.getResultsCount()
    os.sleep(0.05)
    delay = delay + 1
  until (numResults ~= nil and numResults ~= -1) or delay > 10
  
  redraw()
  
  drawContact(radarX, radarY, radarZ, "RAD", colors.yellow)
  
  if numResults ~= nil and numResults > 0 then
    for i = 0, numResults-1 do
      local success, _, name, cx, cy, cz = radar.getResult(i)
      if success then
        drawContact(cx, cy, cz, name, colors.red)
      end
    end
  end
  
  os.sleep(scanDuration)
end

function redraw()
  colorScreen(colors.green)
  
  paintutils.drawLine(1, 1, w, 1, colors.black)
  
  textOut((w / 2) - 7, 1, "= Q-Radar v0.4 =", colors.white, colors.black)
  
  paintutils.drawLine(1, h, w, h, colors.black)
  local energyStored, _, energyUnits = radar.getEnergyStatus()
  if energyStored == nil then energyStored = 0 end
  textOut(4, h, "Energy: " .. energyStored .. " " .. energyUnits .. " | Scan radius: " .. radius, colors.white, colors.black)
end

local continue = true
while continue do
  scanAndDraw()
  os.sleep(0)
end

term.clear()
