'use strict';

var colorize = require('../../_virtual/colorize.js');
var safe = require('../@colors/colors/safe.js');
require('../triple-beam/index.js');
var index = require('../../_virtual/index12.js');

var hasRequiredColorize;

function requireColorize () {
	if (hasRequiredColorize) return colorize.__module.exports;
	hasRequiredColorize = 1;

	const colors = safe.__require();
	const { LEVEL, MESSAGE } = index.__exports;

	//
	// Fix colors not appearing in non-tty environments
	//
	colors.enabled = true;

	/**
	 * @property {RegExp} hasSpace
	 * Simple regex to check for presence of spaces.
	 */
	const hasSpace = /\s+/;

	/*
	 * Colorizer format. Wraps the `level` and/or `message` properties
	 * of the `info` objects with ANSI color codes based on a few options.
	 */
	class Colorizer {
	  constructor(opts = {}) {
	    if (opts.colors) {
	      this.addColors(opts.colors);
	    }

	    this.options = opts;
	  }

	  /*
	   * Adds the colors Object to the set of allColors
	   * known by the Colorizer
	   *
	   * @param {Object} colors Set of color mappings to add.
	   */
	  static addColors(clrs) {
	    const nextColors = Object.keys(clrs).reduce((acc, level) => {
	      acc[level] = hasSpace.test(clrs[level])
	        ? clrs[level].split(hasSpace)
	        : clrs[level];

	      return acc;
	    }, {});

	    Colorizer.allColors = Object.assign({}, Colorizer.allColors || {}, nextColors);
	    return Colorizer.allColors;
	  }

	  /*
	   * Adds the colors Object to the set of allColors
	   * known by the Colorizer
	   *
	   * @param {Object} colors Set of color mappings to add.
	   */
	  addColors(clrs) {
	    return Colorizer.addColors(clrs);
	  }

	  /*
	   * function colorize (lookup, level, message)
	   * Performs multi-step colorization using @colors/colors/safe
	   */
	  colorize(lookup, level, message) {
	    if (typeof message === 'undefined') {
	      message = level;
	    }

	    //
	    // If the color for the level is just a string
	    // then attempt to colorize the message with it.
	    //
	    if (!Array.isArray(Colorizer.allColors[lookup])) {
	      return colors[Colorizer.allColors[lookup]](message);
	    }

	    //
	    // If it is an Array then iterate over that Array, applying
	    // the colors function for each item.
	    //
	    for (let i = 0, len = Colorizer.allColors[lookup].length; i < len; i++) {
	      message = colors[Colorizer.allColors[lookup][i]](message);
	    }

	    return message;
	  }

	  /*
	   * function transform (info, opts)
	   * Attempts to colorize the { level, message } of the given
	   * `logform` info object.
	   */
	  transform(info, opts) {
	    if (opts.all && typeof info[MESSAGE] === 'string') {
	      info[MESSAGE] = this.colorize(info[LEVEL], info.level, info[MESSAGE]);
	    }

	    if (opts.level || opts.all || !opts.message) {
	      info.level = this.colorize(info[LEVEL], info.level);
	    }

	    if (opts.all || opts.message) {
	      info.message = this.colorize(info[LEVEL], info.level, info.message);
	    }

	    return info;
	  }
	}

	/*
	 * function colorize (info)
	 * Returns a new instance of the colorize Format that applies
	 * level colors to `info` objects. This was previously exposed
	 * as { colorize: true } to transports in `winston < 3.0.0`.
	 */
	colorize.__module.exports = opts => new Colorizer(opts);

	//
	// Attach the Colorizer for registration purposes
	//
	colorize.__module.exports.Colorizer
	  = colorize.__module.exports.Format
	  = Colorizer;
	return colorize.__module.exports;
}

exports.__require = requireColorize;
