/* eslint-disable no-console */
'use strict';

type Logger = {
  error: (...args: any[]) => void;
  group: (...args: any[]) => void;
  groupEnd: (...args: any[]) => void;
  info: (...args: any[]) => void;
  log: (...args: any[]) => void;
  table: (...args: any[]) => void;
  warn: (...args: any[]) => void;
};

enum Log {
  Error = 'error',
  Group = 'group',
  GroupEnd = 'groupEnd',
  Info = 'info',
  Log = 'log',
  Table = 'table',
  Warn = 'warn',
}

type Styles = Partial<Record<Log, string>>;

const styles: Styles = {
  error: 'color: #FF5E74; font-weight: bold',
  group: 'color: #0074D9; font-weight: bold',
  info: 'color: #2525A3; font-weight: normal',
  log: 'color: #03A9F4; font-weight: normal',
  warn: 'color: #FFA500; font-weight: bold',
};

function print(...args: any[]) {
  const [type, firstLevel, ...rest] = args;
  const style = styles[type] || styles.log;

  if (type === 'groupEnd') {
    console.groupEnd();
  } else {
    const t = [Log.Warn, Log.Error].includes(type) ? 'log' : type;

    if (typeof firstLevel === 'string' && typeof window !== 'undefined') {
      console[t](`%c ${firstLevel}`, style, ...rest);
    } else {
      console[t](firstLevel, null, ...rest);
    }
  }
}

const theLogger: Logger = {
  error: function (...args: any[]) {
    print(Log.Error, ...args);
  },
  group: function (...args: any[]) {
    print(Log.Group, ...args);
  },
  groupEnd: function () {
    print(Log.GroupEnd);
  },
  info: function (...args: any[]) {
    print(Log.Info, ...args);
  },
  log: function (...args: any[]) {
    print(Log.Log, ...args);
  },
  table: function (...args: any[]) {
    print(Log.Table, ...args);
  },
  warn: function (...args: any[]) {
    print(Log.Warn, ...args);
  },
};

// eslint-disable-next-line @typescript-eslint/no-unused-vars
const noop = (...args: any[]) => null;

const fakeLogger: Logger = {
  error: noop,
  group: noop,
  groupEnd: noop,
  info: noop,
  log: noop,
  table: noop,
  warn: noop,
};

const logger = __DEV__ ? theLogger : fakeLogger;

global.logger = logger;
