if ... ~= "__flib__.format" then
  return require("__flib__.format")
end

--- Various string formatting functions.
--- ```lua
--- local flib_format = require("__flib__.format")
--- ```
--- @class flib_format
local flib_format = {}

local suffix_list = {
  { "Q", 1e30 }, -- quetta
  { "R", 1e27 }, -- ronna
  { "Y", 1e24 }, -- yotta
  { "Z", 1e21 }, -- zetta
  { "E", 1e18 }, -- exa
  { "P", 1e15 }, -- peta
  { "T", 1e12 }, -- tera
  { "G", 1e9 }, -- giga
  { "M", 1e6 }, -- mega
  { "k", 1e3 }, -- kilo
}

--- Format a number for display, adding commas and an optional SI suffix.
--- Specify `fixed_precision` to display the number with the given width,
--- adjusting precision as necessary.
--- @param amount number
--- @param append_suffix boolean?
--- @param fixed_precision number?
--- @return string
function flib_format.number(amount, append_suffix, fixed_precision)
  local suffix = ""
  if append_suffix then
    for _, data in ipairs(suffix_list) do
      if math.abs(amount) >= data[2] then
        amount = amount / data[2]
        suffix = " " .. data[1]
        break
      end
    end
    if not fixed_precision then
      amount = math.floor(amount * 10) / 10
    end
  end
  local formatted, k = tostring(amount), nil
  if fixed_precision then
    -- Show the number with fixed width precision
    local len_before = #tostring(math.floor(amount))
    local len_after = math.max(0, fixed_precision - len_before - 1)
    formatted = string.format("%." .. len_after .. "f", amount)
  end
  -- Add commas to result
  while true do
    formatted, k = string.gsub(formatted, "^(-?%d+)(%d%d%d)", "%1,%2")
    if k == 0 then
      break
    end
  end
  return formatted .. suffix
end

--- Convert the given tick or game.tick into "[hh:]mm:ss" format.
--- @param tick uint?
--- @param include_leading_zeroes boolean?
--- @return string
function flib_format.time(tick, include_leading_zeroes)
  local total_seconds = math.floor((tick or game.ticks_played) / 60)
  local seconds = total_seconds % 60
  local minutes = math.floor(total_seconds / 60)
  if minutes > 59 then
    minutes = minutes % 60
    local hours = math.floor(total_seconds / 3600)
    if include_leading_zeroes then
      return string.format("%02d:%02d:%02d", hours, minutes, seconds)
    else
      return string.format("%d:%02d:%02d", hours, minutes, seconds)
    end
  else
    if include_leading_zeroes then
      return string.format("%02d:%02d", minutes, seconds)
    else
      return string.format("%d:%02d", minutes, seconds)
    end
  end
end

return flib_format
