// LOG LEVELS:
// 0: Fatal
// 1: Error
// 2: Warn
// 3: Info
// 4: Debug
// Logs are written in-memory and logged to console if logLevel > showLogLevel
let loglevel = 0;

export const LEVEL_FATAL = 0;
export const LEVEL_ERROR = 1;
export const LEVEL_WARN = 2;
export const LEVEL_INFO = 3;
export const LEVEL_DEBUG = 4;

interface LogLine {
    level: number,
    module: string,
    message: string,
    timestamp: number,
    deltaStart: number,
    deltaLast: number
}

const debugLog: Array<LogLine> = [];
let timestampStart: number;
let deltaTimestamp: number;
let logger: Logger;
let loggerSetup = false;

export function logSetup() {
    if (loggerSetup) return;
    loggerSetup = true;
    timestampStart = Date.now();
    deltaTimestamp = Date.now();
    logger = new Logger("Logger.ts");
    consoleLogLevel(LEVEL_INFO);
    logger.info("Logger setup complete");
}

function log(level: number, module: string, message: string) {
    const log = {
        level: level,
        module: module,
        message: message,
        timestamp: Date.now(),
        deltaStart: Date.now() - timestampStart,
        deltaLast: Date.now() - deltaTimestamp
    };
    deltaTimestamp = Date.now();

    debugLog.push(log);

    consoleLogHandler(log);
}

function consoleLogHandler(log: LogLine) {
    if (import.meta.env.SSR) return; // no logging in ssr
    if (log.level <= loglevel) {
        let textstyle = "";
        switch (log.level) {
            case 0:
                textstyle = "color:red;font-weight:bold;";
                break;
            case 1:
                textstyle = "color:red;";
                break;
            case 2:
                textstyle = "color:yellow;";
                break;
            case 3:
                textstyle = "";
                break;
            case 4:
                textstyle = "color:gray;";
                break;
        }
        console.log(`%c${new Date(log.timestamp).toISOString()} ${(log.deltaStart / 1000).toFixed(3)}Σ ${(log.deltaLast / 1000).toFixed(3)}Δ\n%c[${log.module}]%c ${log.message}`, "color:gray", "color:#8c188c", textstyle);
    }
}

export function consoleLogLevel(level: number) {
    loglevel = level;
}

export function consoleLogDump() {
    for (let i = 0; i < debugLog.length; i++) {
        consoleLogHandler(debugLog[i]);
    }
}

export class Logger {
    private name: string;

    constructor(name: string) {
        this.name = name;
    }

    fatal(message: any) {
        log(LEVEL_FATAL, this.name, message)
    }

    error(message: any) {
        log(LEVEL_ERROR, this.name, message)
    }

    warn(message: any) {
        log(LEVEL_WARN, this.name, message)
    }

    info(message: any) {
        log(LEVEL_INFO, this.name, message)
    }

    debug(message: any) {
        log(LEVEL_DEBUG, this.name, message)
    }
}