import { LogObject } from 'tachyon-logger/logger';

export function omitMessage(logObj: LogObject): LogObject {
  const { message, ...rest } = logObj;
  return rest;
}

/**
 * Definition of a transformation function for log output. Transformation
 * functions are to be used for handling special logging use-cases or globally
 * adding new logging requirements without altering the calling location.
 *
 * @param logObj The log object to be transformed.
 * @returns      An updated object to be logged in place of the input object.
 */
export type LoggerMiddleware = (logObj: LogObject) => LogObject;

/**
 * If a log message is an array of strings it will join them prior to output.
 *
 * @param logObj The log object to be transformed.
 */
export function singleStringLoggerMiddleware(logObj: LogObject): LogObject {
  if (
    Array.isArray(logObj.message) &&
    logObj.message.every(value => typeof value === 'string')
  ) {
    return {
      message: logObj.message.join(' '),
      ...omitMessage(logObj),
    };
  }
  return logObj;
}

/**
 * If a message is an object that contains a message key, remove the message
 * attribute and move all message attributes to the top level for improved log
 * readability.
 *
 * @param logObj The log object to be transformed.
 */
export function flattenMessageLoggerMiddleware(logObj: LogObject): LogObject {
  if (
    logObj.message instanceof Object &&
    (logObj.message as LogObject).message
  ) {
    return {
      ...(logObj.message as LogObject),
      ...omitMessage(logObj),
    };
  }
  return logObj;
}

/**
 * If a message is an event object, remove the message attribute and move all
 * event attributes to the top level for compatibility with the existing event
 * logger.
 *
 * @param logObj The log object to be transformed.
 */
export function eventLoggerMiddleware(logObj: LogObject): LogObject {
  if (
    logObj.message instanceof Object &&
    (logObj.message as { event: string }).event
  ) {
    return {
      ...(logObj.message as object),
      ...omitMessage(logObj),
    } as LogObject;
  }
  return logObj;
}
