'use strict';

/**
 * Module dependencies.
 */
var EventEmitter = require('events').EventEmitter;
var Hook = require('./hook');
var utils = require('./utils');
var inherits = utils.inherits;
var debug = require('debug')('mocha:suite');
var milliseconds = require('ms');
var errors = require('./errors');
var createInvalidArgumentTypeError = errors.createInvalidArgumentTypeError;

/**
 * Expose `Suite`.
 */

exports = module.exports = Suite;

/**
 * Create a new `Suite` with the given `title` and parent `Suite`.
 *
 * @public
 * @param {Suite} parent - Parent suite (required!)
 * @param {string} title - Title
 * @return {Suite}
 */
Suite.create = function(parent, title) {
  var suite = new Suite(title, parent.ctx);
  suite.parent = parent;
  title = suite.fullTitle();
  parent.addSuite(suite);
  return suite;
};

/**
 * Constructs a new `Suite` instance with the given `title`, `ctx`, and `isRoot`.
 *
 * @public
 * @class
 * @extends EventEmitter
 * @see {@link https://nodejs.org/api/events.html#events_class_eventemitter|EventEmitter}
 * @param {string} title - Suite title.
 * @param {Context} parentContext - Parent context instance.
 * @param {boolean} [isRoot=false] - Whether this is the root suite.
 */
function Suite(title, parentContext, isRoot) {
  if (!utils.isString(title)) {
    throw createInvalidArgumentTypeError(
      'Suite argument "title" must be a string. Received type "' +
        typeof title +
        '"',
      'title',
      'string'
    );
  }
  this.title = title;
  function Context() {}
  Context.prototype = parentContext;
  this.ctx = new Context();
  this.suites = [];
  this.tests = [];
  this.pending = false;
  this._beforeEach = [];
  this._beforeAll = [];
  this._afterEach = [];
  this._afterAll = [];
  this.root = isRoot === true;
  this._timeout = 2000;
  this._enableTimeouts = true;
  this._slow = 75;
  this._bail = false;
  this._retries = -1;
  this._onlyTests = [];
  this._onlySuites = [];
  this.delayed = false;

  this.on('newListener', function(event) {
    if (deprecatedEvents[event]) {
      utils.deprecate(
        'Event "' +
          event +
          '" is deprecated.  Please let the Mocha team know about your use case: https://git.io/v6Lwm'
      );
    }
  });
}

/**
 * Inherit from `EventEmitter.prototype`.
 */
inherits(Suite, EventEmitter);

/**
 * Return a clone of this `Suite`.
 *
 * @private
 * @return {Suite}
 */
Suite.prototype.clone = function() {
  var suite = new Suite(this.title);
  debug('clone');
  suite.ctx = this.ctx;
  suite.root = this.root;
  suite.timeout(this.timeout());
  suite.retries(this.retries());
  suite.enableTimeouts(this.enableTimeouts());
  suite.slow(this.slow());
  suite.bail(this.bail());
  return suite;
};

/**
 * Set or get timeout `ms` or short-hand such as "2s".
 *
 * @private
 * @todo Do not attempt to set value if `ms` is undefined
 * @param {number|string} ms
 * @return {Suite|number} for chaining
 */
Suite.prototype.timeout = function(ms) {
  if (!arguments.length) {
    return this._timeout;
  }
  if (ms.toString() === '0') {
    this._enableTimeouts = false;
  }
  if (typeof ms === 'string') {
    ms = milliseconds(ms);
  }
  debug('timeout %d', ms);
  this._timeout = parseInt(ms, 10);
  return this;
};

/**
 * Set or get number of times to retry a failed test.
 *
 * @private
 * @param {number|string} n
 * @return {Suite|number} for chaining
 */
Suite.prototype.retries = function(n) {
  if (!arguments.length) {
    return this._retries;
  }
  debug('retries %d', n);
  this._retries = parseInt(n, 10) || 0;
  return this;
};

/**
 * Set or get timeout to `enabled`.
 *
 * @private
 * @param {boolean} enabled
 * @return {Suite|boolean} self or enabled
 */
Suite.prototype.enableTimeouts = function(enabled) {
  if (!arguments.length) {
    return this._enableTimeouts;
  }
  debug('enableTimeouts %s', enabled);
  this._enableTimeouts = enabled;
  return this;
};

/**
 * Set or get slow `ms` or short-hand such as "2s".
 *
 * @private
 * @param {number|string} ms
 * @return {Suite|number} for chaining
 */
Suite.prototype.slow = function(ms) {
  if (!arguments.length) {
    return this._slow;
  }
  if (typeof ms === 'string') {
    ms = milliseconds(ms);
  }
  debug('slow %d', ms);
  this._slow = ms;
  return this;
};

/**
 * Set or get whether to bail after first error.
 *
 * @private
 * @param {boolean} bail
 * @return {Suite|number} for chaining
 */
Suite.prototype.bail = function(bail) {
  if (!arguments.length) {
    return this._bail;
  }
  debug('bail %s', bail);
  this._bail = bail;
  return this;
};

/**
 * Check if this suite or its parent suite is marked as pending.
 *
 * @private
 */
Suite.prototype.isPending = function() {
  return this.pending || (this.parent && this.parent.isPending());
};

/**
 * Generic hook-creator.
 * @private
 * @param {string} title - Title of hook
 * @param {Function} fn - Hook callback
 * @returns {Hook} A new hook
 */
Suite.prototype._createHook = function(title, fn) {
  var hook = new Hook(title, fn);
  hook.parent = this;
  hook.timeout(this.timeout());
  hook.retries(this.retries());
  hook.enableTimeouts(this.enableTimeouts());
  hook.slow(this.slow());
  hook.ctx = this.ctx;
  hook.file = this.file;
  return hook;
};

/**
 * Run `fn(test[, done])` before running tests.
 *
 * @private
 * @param {string} title
 * @param {Function} fn
 * @return {Suite} for chaining
 */
Suite.prototype.beforeAll = function(title, fn) {
  if (this.isPending()) {
    return this;
  }
  if (typeof title === 'function') {
    fn = title;
    title = fn.name;
  }
  title = '"before all" hook' + (title ? ': ' + title : '');

  var hook = this._createHook(title, fn);
  this._beforeAll.push(hook);
  this.emit(constants.EVENT_SUITE_ADD_HOOK_BEFORE_ALL, hook);
  return this;
};

/**
 * Run `fn(test[, done])` after running tests.
 *
 * @private
 * @param {string} title
 * @param {Function} fn
 * @return {Suite} for chaining
 */
Suite.prototype.afterAll = function(title, fn) {
  if (this.isPending()) {
    return this;
  }
  if (typeof title === 'function') {
    fn = title;
    title = fn.name;
  }
  title = '"after all" hook' + (title ? ': ' + title : '');

  var hook = this._createHook(title, fn);
  this._afterAll.push(hook);
  this.emit(constants.EVENT_SUITE_ADD_HOOK_AFTER_ALL, hook);
  return this;
};

/**
 * Run `fn(test[, done])` before each test case.
 *
 * @private
 * @param {string} title
 * @param {Function} fn
 * @return {Suite} for chaining
 */
Suite.prototype.beforeEach = function(title, fn) {
  if (this.isPending()) {
    return this;
  }
  if (typeof title === 'function') {
    fn = title;
    title = fn.name;
  }
  title = '"before each" hook' + (title ? ': ' + title : '');

  var hook = this._createHook(title, fn);
  this._beforeEach.push(hook);
  this.emit(constants.EVENT_SUITE_ADD_HOOK_BEFORE_EACH, hook);
  return this;
};

/**
 * Run `fn(test[, done])` after each test case.
 *
 * @private
 * @param {string} title
 * @param {Function} fn
 * @return {Suite} for chaining
 */
Suite.prototype.afterEach = function(title, fn) {
  if (this.isPending()) {
    return this;
  }
  if (typeof title === 'function') {
    fn = title;
    title = fn.name;
  }
  title = '"after each" hook' + (title ? ': ' + title : '');

  var hook = this._createHook(title, fn);
  this._afterEach.push(hook);
  this.emit(constants.EVENT_SUITE_ADD_HOOK_AFTER_EACH, hook);
  return this;
};

/**
 * Add a test `suite`.
 *
 * @private
 * @param {Suite} suite
 * @return {Suite} for chaining
 */
Suite.prototype.addSuite = function(suite) {
  suite.parent = this;
  suite.root = false;
  suite.timeout(this.timeout());
  suite.retries(this.retries());
  suite.enableTimeouts(this.enableTimeouts());
  suite.slow(this.slow());
  suite.bail(this.bail());
  this.suites.push(suite);
  this.emit(constants.EVENT_SUITE_ADD_SUITE, suite);
  return this;
};

/**
 * Add a `test` to this suite.
 *
 * @private
 * @param {Test} test
 * @return {Suite} for chaining
 */
Suite.prototype.addTest = function(test) {
  test.parent = this;
  test.timeout(this.timeout());
  test.retries(this.retries());
  test.enableTimeouts(this.enableTimeouts());
  test.slow(this.slow());
  test.ctx = this.ctx;
  this.tests.push(test);
  this.emit(constants.EVENT_SUITE_ADD_TEST, test);
  return this;
};

/**
 * Return the full title generated by recursively concatenating the parent's
 * full title.
 *
 * @memberof Suite
 * @public
 * @return {string}
 */
Suite.prototype.fullTitle = function() {
  return this.titlePath().join(' ');
};

/**
 * Return the title path generated by recursively concatenating the parent's
 * title path.
 *
 * @memberof Suite
 * @public
 * @return {string}
 */
Suite.prototype.titlePath = function() {
  var result = [];
  if (this.parent) {
    result = result.concat(this.parent.titlePath());
  }
  if (!this.root) {
    result.push(this.title);
  }
  return result;
};

/**
 * Return the total number of tests.
 *
 * @memberof Suite
 * @public
 * @return {number}
 */
Suite.prototype.total = function() {
  return (
    this.suites.reduce(function(sum, suite) {
      return sum + suite.total();
    }, 0) + this.tests.length
  );
};

/**
 * Iterates through each suite recursively to find all tests. Applies a
 * function in the format `fn(test)`.
 *
 * @private
 * @param {Function} fn
 * @return {Suite}
 */
Suite.prototype.eachTest = function(fn) {
  this.tests.forEach(fn);
  this.suites.forEach(function(suite) {
    suite.eachTest(fn);
  });
  return this;
};

/**
 * This will run the root suite if we happen to be running in delayed mode.
 * @private
 */
Suite.prototype.run = function run() {
  if (this.root) {
    this.emit(constants.EVENT_ROOT_SUITE_RUN);
  }
};

/**
 * Determines whether a suite has an `only` test or suite as a descendant.
 *
 * @private
 * @returns {Boolean}
 */
Suite.prototype.hasOnly = function hasOnly() {
  return (
    this._onlyTests.length > 0 ||
    this._onlySuites.length > 0 ||
    this.suites.some(function(suite) {
      return suite.hasOnly();
    })
  );
};

/**
 * Filter suites based on `isOnly` logic.
 *
 * @private
 * @returns {Boolean}
 */
Suite.prototype.filterOnly = function filterOnly() {
  if (this._onlyTests.length) {
    // If the suite contains `only` tests, run those and ignore any nested suites.
    this.tests = this._onlyTests;
    this.suites = [];
  } else {
    // Otherwise, do not run any of the tests in this suite.
    this.tests = [];
    this._onlySuites.forEach(function(onlySuite) {
      // If there are other `only` tests/suites nested in the current `only` suite, then filter that `only` suite.
      // Otherwise, all of the tests on this `only` suite should be run, so don't filter it.
      if (onlySuite.hasOnly()) {
        onlySuite.filterOnly();
      }
    });
    // Run the `only` suites, as well as any other suites that have `only` tests/suites as descendants.
    var onlySuites = this._onlySuites;
    this.suites = this.suites.filter(function(childSuite) {
      return onlySuites.indexOf(childSuite) !== -1 || childSuite.filterOnly();
    });
  }
  // Keep the suite only if there is something to run
  return this.tests.length > 0 || this.suites.length > 0;
};

/**
 * Adds a suite to the list of subsuites marked `only`.
 *
 * @private
 * @param {Suite} suite
 */
Suite.prototype.appendOnlySuite = function(suite) {
  this._onlySuites.push(suite);
};

/**
 * Adds a test to the list of tests marked `only`.
 *
 * @private
 * @param {Test} test
 */
Suite.prototype.appendOnlyTest = function(test) {
  this._onlyTests.push(test);
};

/**
 * Returns the array of hooks by hook name; see `HOOK_TYPE_*` constants.
 * @private
 */
Suite.prototype.getHooks = function getHooks(name) {
  return this['_' + name];
};

/**
 * Cleans up the references to all the deferred functions
 * (before/after/beforeEach/afterEach) and tests of a Suite.
 * These must be deleted otherwise a memory leak can happen,
 * as those functions may reference variables from closures,
 * thus those variables can never be garbage collected as long
 * as the deferred functions exist.
 *
 * @private
 */
Suite.prototype.cleanReferences = function cleanReferences() {
  function cleanArrReferences(arr) {
    for (var i = 0; i < arr.length; i++) {
      delete arr[i].fn;
    }
  }

  if (Array.isArray(this._beforeAll)) {
    cleanArrReferences(this._beforeAll);
  }

  if (Array.isArray(this._beforeEach)) {
    cleanArrReferences(this._beforeEach);
  }

  if (Array.isArray(this._afterAll)) {
    cleanArrReferences(this._afterAll);
  }

  if (Array.isArray(this._afterEach)) {
    cleanArrReferences(this._afterEach);
  }

  for (var i = 0; i < this.tests.length; i++) {
    delete this.tests[i].fn;
  }
};

var constants = utils.defineConstants(
  /**
   * {@link Suite}-related constants.
   * @public
   * @memberof Suite
   * @alias constants
   * @readonly
   * @static
   * @enum {string}
   */
  {
    /**
     * Event emitted after a test file has been loaded Not emitted in browser.
     */
    EVENT_FILE_POST_REQUIRE: 'post-require',
    /**
     * Event emitted before a test file has been loaded. In browser, this is emitted once an interface has been selected.
     */
    EVENT_FILE_PRE_REQUIRE: 'pre-require',
    /**
     * Event emitted immediately after a test file has been loaded. Not emitted in browser.
     */
    EVENT_FILE_REQUIRE: 'require',
    /**
     * Event emitted when `global.run()` is called (use with `delay` option)
     */
    EVENT_ROOT_SUITE_RUN: 'run',

    /**
     * Namespace for collection of a `Suite`'s "after all" hooks
     */
    HOOK_TYPE_AFTER_ALL: 'afterAll',
    /**
     * Namespace for collection of a `Suite`'s "after each" hooks
     */
    HOOK_TYPE_AFTER_EACH: 'afterEach',
    /**
     * Namespace for collection of a `Suite`'s "before all" hooks
     */
    HOOK_TYPE_BEFORE_ALL: 'beforeAll',
    /**
     * Namespace for collection of a `Suite`'s "before all" hooks
     */
    HOOK_TYPE_BEFORE_EACH: 'beforeEach',

    // the following events are all deprecated

    /**
     * Emitted after an "after all" `Hook` has been added to a `Suite`. Deprecated
     */
    EVENT_SUITE_ADD_HOOK_AFTER_ALL: 'afterAll',
    /**
     * Emitted after an "after each" `Hook` has been added to a `Suite` Deprecated
     */
    EVENT_SUITE_ADD_HOOK_AFTER_EACH: 'afterEach',
    /**
     * Emitted after an "before all" `Hook` has been added to a `Suite` Deprecated
     */
    EVENT_SUITE_ADD_HOOK_BEFORE_ALL: 'beforeAll',
    /**
     * Emitted after an "before each" `Hook` has been added to a `Suite` Deprecated
     */
    EVENT_SUITE_ADD_HOOK_BEFORE_EACH: 'beforeEach',
    /**
     * Emitted after a child `Suite` has been added to a `Suite`. Deprecated
     */
    EVENT_SUITE_ADD_SUITE: 'suite',
    /**
     * Emitted after a `Test` has been added to a `Suite`. Deprecated
     */
    EVENT_SUITE_ADD_TEST: 'test'
  }
);

/**
 * @summary There are no known use cases for these events.
 * @desc This is a `Set`-like object having all keys being the constant's string value and the value being `true`.
 * @todo Remove eventually
 * @type {Object<string,boolean>}
 * @ignore
 */
var deprecatedEvents = Object.keys(constants)
  .filter(function(constant) {
    return constant.substring(0, 15) === 'EVENT_SUITE_ADD';
  })
  .reduce(function(acc, constant) {
    acc[constants[constant]] = true;
    return acc;
  }, utils.createMap());

Suite.constants = constants;
