local totalCraftables = 0
local totalUsedPower = 0
local totalStoredPower = 0
local totalMaxStoredPower = 0
local totalIdlePower = 0
local currentCCLine = 1

function round(num, idp)
  local mult = 10^(idp or 0)
  return math.floor(num * mult + 0.5) / mult
end

function r(n)
  return round(n, 2)
end

function reset()
  totalCraftables = 0
  totalUsedPower = 0
  totalStoredPower = 0
  totalMaxStoredPower = 0
  totalIdlePower = 0
  currentCCLine = 1
end
peripheral.wrap("top").clear()

function showMeStatus(name, side, color, line, col)
  local me = peripheral.wrap(side)
  items = me.getAvailableItems(false)
  local uniqItemCount = 0
  local uniqFluidCount = 0
  local itemCount = 0
  local fluidCount = 0
  local craftables = 0
  for key, val in pairs(items) do
    if val.is_fluid then
      uniqFluidCount = uniqFluidCount + 1
      fluidCount = fluidCount + val.size
    end
    if val.is_item then
      uniqItemCount = uniqItemCount + 1
      itemCount = itemCount + val.size
    end
    if val.is_craftable then
      craftables = craftables + 1
      totalCraftables = totalCraftables + 1
    end
  end
  local storedPower = me.getStoredPower()
  totalStoredPower = totalStoredPower + storedPower
  local maxStoredPower = me.getMaxStoredPower()
  totalMaxStoredPower = totalMaxStoredPower + maxStoredPower
  local usedPower = me.getAvgPowerUsage()
  totalUsedPower = totalUsedPower + usedPower
  local genPower = me.getAvgPowerInjection()
  local idlePower = me.getIdlePowerUsage()
  totalIdlePower = totalIdlePower + idlePower
  local craftingCpus = me.getCraftingCPUs()
  local nameLen = string.len(name)
  local off = 2 + nameLen
  writeLine(color, col, 0, line, string.format("%s: i:%d u:%d c:%d", name, itemCount, uniqItemCount, craftables), true)
  writeLine(color, col, off, line + 1, string.format("sp:%.2f/%.2f MRF (%.2f%%)", r(storedPower * 2 / 1000000), r(maxStoredPower * 2 / 1000000), r(storedPower * 100 / maxStoredPower)), true)
  writeLine(color, col, off, line + 2, string.format("up:%.2f/%.2f kRF/t (%.2f%%)", r(usedPower * 2 / 1000), r(idlePower * 2 / 1000), r(usedPower * 100 / idlePower)), true)
  writeLine(color, col, off, line + 3, string.format("gp:%.2f kRF/t (%.2f%%)", r(genPower * 2 / 1000), r(genPower * 100 / usedPower)), true)
  writeCraftingCpus(name, color, craftingCpus)
end

function writeCraftingCpus(name, color, craftingCpus)
  local mon = peripheral.wrap("top")
  for k, v in pairs(craftingCpus) do
    local status = "?"
    local otherColor = colors.red
    if v.busy then
      otherColor = colors.red
      status = "b"
    else
      otherColor = colors.green
      status = "f"
    end
    writeLine(color, 1, 0, currentCCLine, string.format("%s: ", name), true)
    writeLine(otherColor, 1, string.len(name .. ": "), currentCCLine, string.format("s:%dk p:%d s:%s", v.storage / 1024, v.coprocessors, status), false)
    currentCCLine = currentCCLine + 1
  end
end

function writeLine(color, col, off, line, str, clear)
  local colWidth = 45
  local mon = peripheral.wrap("top")
  mon.setCursorPos(col * colWidth + 1, line)
  mon.setTextColor(color)
  if clear then
    mon.write(string.format("%s%s%s", str.rep(" ", off), str, string.rep(" ", colWidth - string.len(str) - off)))
  else
    mon.setCursorPos(col * colWidth + 1 + off, line)
    mon.write(str)
  end
end

function showMeOverall(line, color)
  writeLine(color, 0, 0, line, string.format(" TOTAL: c:%d", totalCraftables), true)
  writeLine(color, 0, 8, line + 1, string.format("sp:%.2f/%.2f MRF (%.2f%%)", r(totalStoredPower * 2 / 1000000), r(totalMaxStoredPower * 2 / 1000000), r(totalStoredPower * 100 / totalMaxStoredPower)), true)
  writeLine(color, 0, 8, line + 2, string.format("up:%.2f/%.2f kRF/t (%.2f%%)", r(totalUsedPower * 2 / 1000), r(totalIdlePower * 2 / 1000), r(totalUsedPower * 100 / totalIdlePower)), true)
end

function showAll()
  reset()
  showMeStatus("  Main", "front", colors.purple, 1, 0)
  showMeStatus("Yellow", "back", colors.yellow, 5, 0)
  showMeStatus("   Red", "left", colors.red, 9, 0)
  showMeStatus("Orange", "right", colors.orange, 13, 0)
  showMeStatus("  Blue", "bottom", colors.blue, 17, 0)
  showMeOverall(21, colors.white)
end

while true do
  showAll()
  os.sleep(1)
end
