local DR = select(2, ...)
local constants = DR.Modules["Core.Constants"]

local LogService = {
  _db = nil,
  _cache = {},
}

local function joinArgs(...)
  local n = select("#", ...)
  local out = {}
  for i = 1, n do
    out[i] = tostring(select(i, ...))
  end
  return table.concat(out, " ")
end

local function appendEntry(db, entry)
  local logs = db.global.logs
  logs[#logs + 1] = entry

  local cap = constants.LIMITS.LOG_ENTRIES
  if #logs > cap then
    local overflow = #logs - cap
    for _ = 1, overflow do
      table.remove(logs, 1)
    end
  end
end

local Logger = {}
Logger.__index = Logger

function Logger:_write(level, ...)
  if not LogService._db then
    return
  end

  if level == "DEBUG" and not LogService._db.profile.debugEnabled then
    return
  end

  local message = joinArgs(...)
  local entry = {
    ts = time(),
    lvl = level,
    name = self.name,
    msg = message,
  }

  appendEntry(LogService._db, entry)

  if level ~= "DEBUG" then
    DR:Print("DetentionRolls [" .. self.name .. "]", message)
  end
end

function Logger:d(...)
  self:_write("DEBUG", ...)
end

function Logger:i(...)
  self:_write("INFO", ...)
end

function Logger:w(...)
  self:_write("WARN", ...)
end

function Logger:e(...)
  self:_write("ERROR", ...)
end

function LogService:SetDb(db)
  self._db = db
end

function LogService:Get(name)
  name = name or "Core"
  if not self._cache[name] then
    self._cache[name] = setmetatable({ name = name }, Logger)
  end
  return self._cache[name]
end

DR:RegisterModule("Services.Log", LogService)
