-- Logging module.
-- Provides local functions to log messages with different severities.
-- Messages can be printed to the terminal and/or written to a log file.
-- @module logging

--- The different severities of log messages.
-- @table LOG_LEVELS
-- @field DEBUG The debug severity.
-- @field INFO The info severity.
-- @field SUCCESS The success severity.
-- @field WARN The warning severity.
-- @field ERROR The error severity.

local expect = require("cc.expect").expect

local LOG_LEVELS = {
    {
        name = "DEBUG",         -- do NOT change
        color = colors.white,
        number = 0              -- do NOT change
    },
    {
        name = "INFO",          -- do NOT change
        color = colors.blue,
        number = 1              -- do NOT change
    },
    {
        name = "SUCCESS",       -- do NOT change
        color = colors.green,
        number = 2              -- do NOT change
    },
    {
        name = "WARN",          -- do NOT change
        color = colors.yellow,
        number = 3              -- do NOT change
    },
    {
        name = "ERROR",         -- do NOT change
        color = colors.red,
        number = 4              -- do NOT change
    }
}

local function write_log(level, message)
    expect(1, level, "number")
    expect(2, message, "string")
    if level < MIN_LOG_LEVEL then
        return
    end

    local level_index = math.min(math.max(level, 0), #LOG_LEVELS-1)
    local level_data = LOG_LEVELS[level_index+1]
    local color_before = term.getTextColor()

    if PRINT_TO_TERM then
        term.setTextColor(level_data.color)
        print("[" .. string.upper(level_data.name) .. "] " .. message)
        term.setTextColor(color_before)
    end

    if FILENAME ~= "" then
        local file = io.open(FILENAME, "a")
        if file then
            file:write(os.date("[%Y-%m-%d %H:%M:%S]: [" .. string.upper(level_data.name) .. "] ") .. message .. "\n")
            file:close()
        else
            print("Error: Failed to open log file")
        end
    end
end

--- Initializes the logging module.
--- @param level number The minimum severity level of messages to be logged.
--- @param print_to_term boolean If `true`, messages will be printed to the terminal.
--- @param filename string The name of the log file. An empty string disables file 
local function init(level, print_to_term, filename)
    expect(1, level, "number")
    expect(2, print_to_term, "boolean")
    expect(3, filename, "string", "nil")
    MIN_LOG_LEVEL = level
    PRINT_TO_TERM = print_to_term
    FILENAME = filename
end

--- Logs a debug message.
--- @param message string The debug message to be logged.
local function debug(message)
    expect(1, message, "string")
    write_log(0, message)
end

--- Logs an info message.
--- @param message string The info message to be logged.
local function info(message)
    expect(1, message, "string")
    write_log(1, message)
end

--- Logs a success message.
--- @param message string The success message to be logged.
local function success(message)
    expect(1, message, "string")
    write_log(2, message)
end

--- Logs a warning message.
--- @param message string The warning message to be logged.
local function warning(message)
    expect(1, message, "string")
    write_log(3, message)
end

--- Logs an error message.
--- @param message string The error message to be logged.
local function error(message)
    expect(1, message, "string")
    write_log(4, message)
end

return {
    init = init,
    debug = debug,
    info = info,
    success = success,
    warning = warning,
    error = error
}