import { EventEmitter } from "https://deno.land/x/evtemitter@v3.0.0/mod.ts";
import { LOG_LEVEL as _LOG_LEVEL } from "@lib/env.ts";

enum LOG_LEVEL {
  DEBUG = 0,
  INFO = 1,
  WARN = 2,
  ERROR = 3,
}

const logMap = {
  "debug": LOG_LEVEL.DEBUG,
  "info": LOG_LEVEL.INFO,
  "warn": LOG_LEVEL.WARN,
  "error": LOG_LEVEL.ERROR,
} as const;

const logFuncs = {
  [LOG_LEVEL.DEBUG]: console.debug,
  [LOG_LEVEL.INFO]: console.info,
  [LOG_LEVEL.WARN]: console.warn,
  [LOG_LEVEL.ERROR]: console.error,
} as const;

let longestScope = 0;
let logLevel = (_LOG_LEVEL && _LOG_LEVEL in logMap && logMap[_LOG_LEVEL]) ??
  LOG_LEVEL.WARN;

const ee = new EventEmitter<{
  log: { level: LOG_LEVEL; scope: string; args: unknown[] };
}>();

export function setLogLevel(level: LOG_LEVEL) {
  logLevel = level;
}

type LoggerOptions = {
  enabled?: boolean;
};

const createLogFunction =
  (scope: string, level: LOG_LEVEL) => (...data: unknown[]) => {
    ee.emit("log", { level, scope, args: data });
    if (level <= logLevel) return;
    logFuncs[level](`[${scope.padEnd(longestScope, " ")}]`, ...data);
  };

export function createLogger(scope: string, _options?: LoggerOptions) {
  longestScope = Math.max(scope.length, longestScope);

  return {
    debug: createLogFunction(scope, LOG_LEVEL.DEBUG),
    info: createLogFunction(scope, LOG_LEVEL.INFO),
    error: createLogFunction(scope, LOG_LEVEL.ERROR),
    warn: createLogFunction(scope, LOG_LEVEL.WARN),
    addEventListener:
      ((type, cb) =>
        ee.addEventListener(type, cb)) as typeof ee.addEventListener,
  };
}
