'use strict';

var EventEmitter = require('events').EventEmitter;
var Pending = require('./pending');
var debug = require('debug')('mocha:runnable');
var milliseconds = require('ms');
var utils = require('./utils');
var createInvalidExceptionError = require('./errors')
  .createInvalidExceptionError;

/**
 * Save timer references to avoid Sinon interfering (see GH-237).
 */
var Date = global.Date;
var setTimeout = global.setTimeout;
var clearTimeout = global.clearTimeout;
var toString = Object.prototype.toString;

module.exports = Runnable;

/**
 * Initialize a new `Runnable` with the given `title` and callback `fn`.
 *
 * @class
 * @extends external:EventEmitter
 * @public
 * @param {String} title
 * @param {Function} fn
 */
function Runnable(title, fn) {
  this.title = title;
  this.fn = fn;
  this.body = (fn || '').toString();
  this.async = fn && fn.length;
  this.sync = !this.async;
  this._timeout = 2000;
  this._slow = 75;
  this._enableTimeouts = true;
  this.timedOut = false;
  this._retries = -1;
  this._currentRetry = 0;
  this.pending = false;
}

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

/**
 * Get current timeout value in msecs.
 *
 * @private
 * @returns {number} current timeout threshold value
 */
/**
 * @summary
 * Set timeout threshold value (msecs).
 *
 * @description
 * A string argument can use shorthand (e.g., "2s") and will be converted.
 * The value will be clamped to range [<code>0</code>, <code>2^<sup>31</sup>-1</code>].
 * If clamped value matches either range endpoint, timeouts will be disabled.
 *
 * @private
 * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout#Maximum_delay_value}
 * @param {number|string} ms - Timeout threshold value.
 * @returns {Runnable} this
 * @chainable
 */
Runnable.prototype.timeout = function(ms) {
  if (!arguments.length) {
    return this._timeout;
  }
  if (typeof ms === 'string') {
    ms = milliseconds(ms);
  }

  // Clamp to range
  var INT_MAX = Math.pow(2, 31) - 1;
  var range = [0, INT_MAX];
  ms = utils.clamp(ms, range);

  // see #1652 for reasoning
  if (ms === range[0] || ms === range[1]) {
    this._enableTimeouts = false;
  }
  debug('timeout %d', ms);
  this._timeout = ms;
  if (this.timer) {
    this.resetTimeout();
  }
  return this;
};

/**
 * Set or get slow `ms`.
 *
 * @private
 * @param {number|string} ms
 * @return {Runnable|number} ms or Runnable instance.
 */
Runnable.prototype.slow = function(ms) {
  if (!arguments.length || typeof ms === 'undefined') {
    return this._slow;
  }
  if (typeof ms === 'string') {
    ms = milliseconds(ms);
  }
  debug('slow %d', ms);
  this._slow = ms;
  return this;
};

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

/**
 * Halt and mark as pending.
 *
 * @memberof Mocha.Runnable
 * @public
 */
Runnable.prototype.skip = function() {
  throw new Pending('sync skip');
};

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

/**
 * Return `true` if this Runnable has failed.
 * @return {boolean}
 * @private
 */
Runnable.prototype.isFailed = function() {
  return !this.isPending() && this.state === constants.STATE_FAILED;
};

/**
 * Return `true` if this Runnable has passed.
 * @return {boolean}
 * @private
 */
Runnable.prototype.isPassed = function() {
  return !this.isPending() && this.state === constants.STATE_PASSED;
};

/**
 * Set or get number of retries.
 *
 * @private
 */
Runnable.prototype.retries = function(n) {
  if (!arguments.length) {
    return this._retries;
  }
  this._retries = n;
};

/**
 * Set or get current retry
 *
 * @private
 */
Runnable.prototype.currentRetry = function(n) {
  if (!arguments.length) {
    return this._currentRetry;
  }
  this._currentRetry = n;
};

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

/**
 * Return the title path generated by concatenating the parent's title path with the title.
 *
 * @memberof Mocha.Runnable
 * @public
 * @return {string}
 */
Runnable.prototype.titlePath = function() {
  return this.parent.titlePath().concat([this.title]);
};

/**
 * Clear the timeout.
 *
 * @private
 */
Runnable.prototype.clearTimeout = function() {
  clearTimeout(this.timer);
};

/**
 * Inspect the runnable void of private properties.
 *
 * @private
 * @return {string}
 */
Runnable.prototype.inspect = function() {
  return JSON.stringify(
    this,
    function(key, val) {
      if (key[0] === '_') {
        return;
      }
      if (key === 'parent') {
        return '#<Suite>';
      }
      if (key === 'ctx') {
        return '#<Context>';
      }
      return val;
    },
    2
  );
};

/**
 * Reset the timeout.
 *
 * @private
 */
Runnable.prototype.resetTimeout = function() {
  var self = this;
  var ms = this.timeout() || 1e9;

  if (!this._enableTimeouts) {
    return;
  }
  this.clearTimeout();
  this.timer = setTimeout(function() {
    if (!self._enableTimeouts) {
      return;
    }
    self.callback(self._timeoutError(ms));
    self.timedOut = true;
  }, ms);
};

/**
 * Set or get a list of whitelisted globals for this test run.
 *
 * @private
 * @param {string[]} globals
 */
Runnable.prototype.globals = function(globals) {
  if (!arguments.length) {
    return this._allowedGlobals;
  }
  this._allowedGlobals = globals;
};

/**
 * Run the test and invoke `fn(err)`.
 *
 * @param {Function} fn
 * @private
 */
Runnable.prototype.run = function(fn) {
  var self = this;
  var start = new Date();
  var ctx = this.ctx;
  var finished;
  var emitted;

  // Sometimes the ctx exists, but it is not runnable
  if (ctx && ctx.runnable) {
    ctx.runnable(this);
  }

  // called multiple times
  function multiple(err) {
    if (emitted) {
      return;
    }
    emitted = true;
    var msg = 'done() called multiple times';
    if (err && err.message) {
      err.message += " (and Mocha's " + msg + ')';
      self.emit('error', err);
    } else {
      self.emit('error', new Error(msg));
    }
  }

  // finished
  function done(err) {
    var ms = self.timeout();
    if (self.timedOut) {
      return;
    }

    if (finished) {
      return multiple(err);
    }

    self.clearTimeout();
    self.duration = new Date() - start;
    finished = true;
    if (!err && self.duration > ms && self._enableTimeouts) {
      err = self._timeoutError(ms);
    }
    fn(err);
  }

  // for .resetTimeout()
  this.callback = done;

  // explicit async with `done` argument
  if (this.async) {
    this.resetTimeout();

    // allows skip() to be used in an explicit async context
    this.skip = function asyncSkip() {
      done(new Pending('async skip call'));
      // halt execution.  the Runnable will be marked pending
      // by the previous call, and the uncaught handler will ignore
      // the failure.
      throw new Pending('async skip; aborting execution');
    };

    if (this.allowUncaught) {
      return callFnAsync(this.fn);
    }
    try {
      callFnAsync(this.fn);
    } catch (err) {
      emitted = true;
      done(Runnable.toValueOrError(err));
    }
    return;
  }

  if (this.allowUncaught) {
    if (this.isPending()) {
      done();
    } else {
      callFn(this.fn);
    }
    return;
  }

  // sync or promise-returning
  try {
    if (this.isPending()) {
      done();
    } else {
      callFn(this.fn);
    }
  } catch (err) {
    emitted = true;
    done(Runnable.toValueOrError(err));
  }

  function callFn(fn) {
    var result = fn.call(ctx);
    if (result && typeof result.then === 'function') {
      self.resetTimeout();
      result.then(
        function() {
          done();
          // Return null so libraries like bluebird do not warn about
          // subsequently constructed Promises.
          return null;
        },
        function(reason) {
          done(reason || new Error('Promise rejected with no or falsy reason'));
        }
      );
    } else {
      if (self.asyncOnly) {
        return done(
          new Error(
            '--async-only option in use without declaring `done()` or returning a promise'
          )
        );
      }

      done();
    }
  }

  function callFnAsync(fn) {
    var result = fn.call(ctx, function(err) {
      if (err instanceof Error || toString.call(err) === '[object Error]') {
        return done(err);
      }
      if (err) {
        if (Object.prototype.toString.call(err) === '[object Object]') {
          return done(
            new Error('done() invoked with non-Error: ' + JSON.stringify(err))
          );
        }
        return done(new Error('done() invoked with non-Error: ' + err));
      }
      if (result && utils.isPromise(result)) {
        return done(
          new Error(
            'Resolution method is overspecified. Specify a callback *or* return a Promise; not both.'
          )
        );
      }

      done();
    });
  }
};

/**
 * Instantiates a "timeout" error
 *
 * @param {number} ms - Timeout (in milliseconds)
 * @returns {Error} a "timeout" error
 * @private
 */
Runnable.prototype._timeoutError = function(ms) {
  var msg =
    'Timeout of ' +
    ms +
    'ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.';
  if (this.file) {
    msg += ' (' + this.file + ')';
  }
  return new Error(msg);
};

var constants = utils.defineConstants(
  /**
   * {@link Runnable}-related constants.
   * @public
   * @memberof Runnable
   * @readonly
   * @static
   * @alias constants
   * @enum {string}
   */
  {
    /**
     * Value of `state` prop when a `Runnable` has failed
     */
    STATE_FAILED: 'failed',
    /**
     * Value of `state` prop when a `Runnable` has passed
     */
    STATE_PASSED: 'passed'
  }
);

/**
 * Given `value`, return identity if truthy, otherwise create an "invalid exception" error and return that.
 * @param {*} [value] - Value to return, if present
 * @returns {*|Error} `value`, otherwise an `Error`
 * @private
 */
Runnable.toValueOrError = function(value) {
  return (
    value ||
    createInvalidExceptionError(
      'Runnable failed with falsy or undefined exception. Please throw an Error instead.',
      value
    )
  );
};

Runnable.constants = constants;
