/**
 * Valid values for a log level. These are added to every logger call.
 */
export enum LogLevel {
  DEBUG = 'DEBUG',
  INFO = 'INFO',
  WARNING = 'WARNING',
  ERROR = 'ERROR',
}

/**
 * Loggers will only log strings or a single Object. If an Object is an array
 * of strings, they will be joined together as the message during log output.
 */
export type LogMessage = string | string[] | object;

/**
 * The basic structure of all log output.
 */
export interface LogObject {
  /**
   * @property  By default, the logged Object or string will be stored in
   *            message.
   *            It is optional, as middleware may reformat the message into a
   *            structure that makes more sense for the logged content.
   */
  readonly message?: LogMessage;
  /**
   * @property  The severity of the log message. This is mandatory and must be
   *            supplied by all loggers.
   */
  readonly level: LogLevel;
  /**
   * @property The time the message was logged.
   */
  readonly time?: number;
}

/**
 * Serialized log formats.
 *
 * A browser will use LogObject to allow the developer to expand the object.
 * CloudWatch accepts stringified JSON to allow JSON searches.
 */
export type LogOutput = LogObject | string;

/**
 * A function for serializing log output to the correct format for the log
 * viewer.
 *
 * @param logObj  The log object to serialize.
 * @returns       The serialized log.
 */
export type LogSerializer = (logObj: LogObject) => LogOutput;

/**
 * The public interface for all loggers.
 */
export interface Logger {
  /**
   * Logs a message with DEBUG severity.
   *
   * @param message  A string or Object to log.
   */
  debug(message: LogMessage): void;
  /**
   * Logs a message with DEBUG severity. This is a usability alias for debug.
   *
   * @param message  A string or Object to log.
   */
  log(message: LogMessage): void;
  /**
   * Logs a message with INFO severity.
   *
   * @param message  A string or Object to log.
   */
  info(message: LogMessage): void;
  /**
   * Logs a message with WARNING severity.
   *
   * @param message  A string or Object to log.
   */
  warn(message: LogMessage): void;
  /**
   * Logs a message with ERROR severity.
   *
   * @param message  A string or Object to log.
   */
  error(message: LogMessage): void;
}
