type LogLevel = "DEBUG" | "INFO" | "WARN" | "ERROR" | "CRITICAL";

export interface LogEntry {
  level: LogLevel;
  message: string;
  timestamp: number;
}

export class LogcatServiceClass {
  private logs: LogEntry[] = [];
  private lastLogTimestamp: number | null = null;
  private listeners: (() => void)[] = [];

  constructor() {
    this.log("LogcatService initialised", "INFO");
  }

  addListener(callback: () => void) {
    this.listeners.push(callback);
  }

  removeListener(callback: () => void) {
    this.listeners = this.listeners.filter((listener) => listener !== callback);
  }

  private notifyListeners() {
    this.listeners.forEach((listener) => listener());
  }

  log(message: string, level: LogLevel = "INFO"): void {
    const currentTimestamp = new Date().getTime();
    const timeSinceLastLog = this.lastLogTimestamp
      ? currentTimestamp - this.lastLogTimestamp
      : 0;

    const logEntry: LogEntry = { message, level, timestamp: timeSinceLastLog };
    this.logs.push(logEntry);

    switch (level) {
      case "DEBUG":
        console.debug(`> [${level}] ${message} (+${timeSinceLastLog}ms)`);
        break;
      case "INFO":
        console.info(`> [${level}] ${message} (+${timeSinceLastLog}ms)`);
        break;
      case "WARN":
        console.warn(`> [${level}] ${message} (+${timeSinceLastLog}ms)`);
        break;
      case "ERROR":
        console.error(`> [${level}] ${message} (+${timeSinceLastLog}ms)`);
        break;
      case "CRITICAL":
        console.error(`> [${level}] ${message} (+${timeSinceLastLog}ms)`);
        break;
    }

    this.lastLogTimestamp = currentTimestamp;
    this.notifyListeners();
  }

  getLogs(): LogEntry[] {
    return this.logs;
  }
}

export const logcat = new LogcatServiceClass();
