“use strict”;

/**

* This is the common logic for both the Node.js and web browser
* implementations of `debug()`.
*/

function setup(env) {

createDebug.debug = createDebug;
createDebug.default = createDebug;
createDebug.coerce = coerce;
createDebug.disable = disable;
createDebug.enable = enable;
createDebug.enabled = enabled;
createDebug.humanize = require('ms');
Object.keys(env).forEach(function (key) {
  createDebug[key] = env[key];
});
/**
* Active `debug` instances.
*/

createDebug.instances = [];
/**
* The currently active debug mode names, and names to skip.
*/

createDebug.names = [];
createDebug.skips = [];
/**
* Map of special "%n" handling functions, for the debug "format" argument.
*
* Valid key names are a single, lower or upper-case letter, i.e. "n" and "N".
*/

createDebug.formatters = {};
/**
* Selects a color for a debug namespace
* @param {String} namespace The namespace string for the for the debug instance to be colored
* @return {Number|String} An ANSI color code for the given namespace
* @api private
*/

function selectColor(namespace) {
  var hash = 0;

  for (var i = 0; i < namespace.length; i++) {
    hash = (hash << 5) - hash + namespace.charCodeAt(i);
    hash |= 0; // Convert to 32bit integer
  }

  return createDebug.colors[Math.abs(hash) % createDebug.colors.length];
}

createDebug.selectColor = selectColor;
/**
* Create a debugger with the given `namespace`.
*
* @param {String} namespace
* @return {Function}
* @api public
*/

function createDebug(namespace) {
  var prevTime;

  function debug() {
    // Disabled?
    if (!debug.enabled) {
      return;
    }

    for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
      args[_key] = arguments[_key];
    }

    var self = debug; // Set `diff` timestamp

    var curr = Number(new Date());
    var ms = curr - (prevTime || curr);
    self.diff = ms;
    self.prev = prevTime;
    self.curr = curr;
    prevTime = curr;
    args[0] = createDebug.coerce(args[0]);

    if (typeof args[0] !== 'string') {
      // Anything else let's inspect with %O
      args.unshift('%O');
    } // Apply any `formatters` transformations

    var index = 0;
    args[0] = args[0].replace(/%([a-zA-Z%])/g, function (match, format) {
      // If we encounter an escaped % then don't increase the array index
      if (match === '%%') {
        return match;
      }

      index++;
      var formatter = createDebug.formatters[format];

      if (typeof formatter === 'function') {
        var val = args[index];
        match = formatter.call(self, val); // Now we need to remove `args[index]` since it's inlined in the `format`

        args.splice(index, 1);
        index--;
      }

      return match;
    }); // Apply env-specific formatting (colors, etc.)

    createDebug.formatArgs.call(self, args);
    var logFn = self.log || createDebug.log;
    logFn.apply(self, args);
  }

  debug.namespace = namespace;
  debug.enabled = createDebug.enabled(namespace);
  debug.useColors = createDebug.useColors();
  debug.color = selectColor(namespace);
  debug.destroy = destroy;
  debug.extend = extend; // Debug.formatArgs = formatArgs;
  // debug.rawLog = rawLog;
  // env-specific initialization logic for debug instances

  if (typeof createDebug.init === 'function') {
    createDebug.init(debug);
  }

  createDebug.instances.push(debug);
  return debug;
}

function destroy() {
  var index = createDebug.instances.indexOf(this);

  if (index !== -1) {
    createDebug.instances.splice(index, 1);
    return true;
  }

  return false;
}

function extend(namespace, delimiter) {
  return createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace);
}
/**
* Enables a debug mode by namespaces. This can include modes
* separated by a colon and wildcards.
*
* @param {String} namespaces
* @api public
*/

function enable(namespaces) {
  createDebug.save(namespaces);
  createDebug.names = [];
  createDebug.skips = [];
  var i;
  var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/);
  var len = split.length;

  for (i = 0; i < len; i++) {
    if (!split[i]) {
      // ignore empty strings
      continue;
    }

    namespaces = split[i].replace(/\*/g, '.*?');

    if (namespaces[0] === '-') {
      createDebug.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
    } else {
      createDebug.names.push(new RegExp('^' + namespaces + '$'));
    }
  }

  for (i = 0; i < createDebug.instances.length; i++) {
    var instance = createDebug.instances[i];
    instance.enabled = createDebug.enabled(instance.namespace);
  }
}
/**
* Disable debug output.
*
* @api public
*/

function disable() {
  createDebug.enable('');
}
/**
* Returns true if the given mode name is enabled, false otherwise.
*
* @param {String} name
* @return {Boolean}
* @api public
*/

function enabled(name) {
  if (name[name.length - 1] === '*') {
    return true;
  }

  var i;
  var len;

  for (i = 0, len = createDebug.skips.length; i < len; i++) {
    if (createDebug.skips[i].test(name)) {
      return false;
    }
  }

  for (i = 0, len = createDebug.names.length; i < len; i++) {
    if (createDebug.names[i].test(name)) {
      return true;
    }
  }

  return false;
}
/**
* Coerce `val`.
*
* @param {Mixed} val
* @return {Mixed}
* @api private
*/

function coerce(val) {
  if (val instanceof Error) {
    return val.stack || val.message;
  }

  return val;
}

createDebug.enable(createDebug.load());
return createDebug;

}

module.exports = setup;