'use strict';

/* eslint no-unused-vars: off */
/* eslint-env commonjs */

/**
 * Shim process.stdout.
 */

process.stdout = require('browser-stdout')({label: false});

var Mocha = require('./lib/mocha');

/**
 * Create a Mocha instance.
 *
 * @return {undefined}
 */

var mocha = new Mocha({reporter: 'html'});

/**
 * Save timer references to avoid Sinon interfering (see GH-237).
 */

var Date = global.Date;
var setTimeout = global.setTimeout;
var setInterval = global.setInterval;
var clearTimeout = global.clearTimeout;
var clearInterval = global.clearInterval;

var uncaughtExceptionHandlers = [];

var originalOnerrorHandler = global.onerror;

/**
 * Remove uncaughtException listener.
 * Revert to original onerror handler if previously defined.
 */

process.removeListener = function(e, fn) {
  if (e === 'uncaughtException') {
    if (originalOnerrorHandler) {
      global.onerror = originalOnerrorHandler;
    } else {
      global.onerror = function() {};
    }
    var i = uncaughtExceptionHandlers.indexOf(fn);
    if (i !== -1) {
      uncaughtExceptionHandlers.splice(i, 1);
    }
  }
};

/**
 * Implements uncaughtException listener.
 */

process.on = function(e, fn) {
  if (e === 'uncaughtException') {
    global.onerror = function(err, url, line) {
      fn(new Error(err + ' (' + url + ':' + line + ')'));
      return !mocha.allowUncaught;
    };
    uncaughtExceptionHandlers.push(fn);
  }
};

// The BDD UI is registered by default, but no UI will be functional in the
// browser without an explicit call to the overridden `mocha.ui` (see below).
// Ensure that this default UI does not expose its methods to the global scope.
mocha.suite.removeAllListeners('pre-require');

var immediateQueue = [];
var immediateTimeout;

function timeslice() {
  var immediateStart = new Date().getTime();
  while (immediateQueue.length && new Date().getTime() - immediateStart < 100) {
    immediateQueue.shift()();
  }
  if (immediateQueue.length) {
    immediateTimeout = setTimeout(timeslice, 0);
  } else {
    immediateTimeout = null;
  }
}

/**
 * High-performance override of Runner.immediately.
 */

Mocha.Runner.immediately = function(callback) {
  immediateQueue.push(callback);
  if (!immediateTimeout) {
    immediateTimeout = setTimeout(timeslice, 0);
  }
};

/**
 * Function to allow assertion libraries to throw errors directly into mocha.
 * This is useful when running tests in a browser because window.onerror will
 * only receive the 'message' attribute of the Error.
 */
mocha.throwError = function(err) {
  uncaughtExceptionHandlers.forEach(function(fn) {
    fn(err);
  });
  throw err;
};

/**
 * Override ui to ensure that the ui functions are initialized.
 * Normally this would happen in Mocha.prototype.loadFiles.
 */

mocha.ui = function(ui) {
  Mocha.prototype.ui.call(this, ui);
  this.suite.emit('pre-require', global, null, this);
  return this;
};

/**
 * Setup mocha with the given setting options.
 */

mocha.setup = function(opts) {
  if (typeof opts === 'string') {
    opts = {ui: opts};
  }
  for (var opt in opts) {
    if (opts.hasOwnProperty(opt)) {
      this[opt](opts[opt]);
    }
  }
  return this;
};

/**
 * Run mocha, returning the Runner.
 */

mocha.run = function(fn) {
  var options = mocha.options;
  mocha.globals('location');

  var query = Mocha.utils.parseQuery(global.location.search || '');
  if (query.grep) {
    mocha.grep(query.grep);
  }
  if (query.fgrep) {
    mocha.fgrep(query.fgrep);
  }
  if (query.invert) {
    mocha.invert();
  }

  return Mocha.prototype.run.call(mocha, function(err) {
    // The DOM Document is not available in Web Workers.
    var document = global.document;
    if (
      document &&
      document.getElementById('mocha') &&
      options.noHighlighting !== true
    ) {
      Mocha.utils.highlightTags('code');
    }
    if (fn) {
      fn(err);
    }
  });
};

/**
 * Expose the process shim.
 * https://github.com/mochajs/mocha/pull/916
 */

Mocha.process = process;

/**
 * Expose mocha.
 */

global.Mocha = Mocha;
global.mocha = mocha;

// this allows test/acceptance/required-tokens.js to pass; thus,
// you can now do `const describe = require('mocha').describe` in a
// browser context (assuming browserification).  should fix #880
module.exports = global;
