/* MK2k: hotfix for vert.x usage */

/** @license MIT License (c) copyright 2010-2014 original author or authors */
/** @author Brian Cavalier */
/** @author John Hann */

/*global process,document,setTimeout,clearTimeout,MutationObserver,WebKitMutationObserver*/
(function (define) {
  "use strict";
  define(function (require) {
    /*jshint maxcomplexity:6*/

    // Sniff "best" async scheduling option
    // Prefer process.nextTick or MutationObserver, then check for
    // setTimeout, and finally vertx, since its the only env that doesn't
    // have setTimeout

    var MutationObs;
    var capturedSetTimeout = typeof setTimeout !== "undefined" && setTimeout;

    // Default env
    var setTimer = function (f, ms) {
      return setTimeout(f, ms);
    };
    var clearTimer = function (t) {
      return clearTimeout(t);
    };
    var asap = function (f) {
      return capturedSetTimeout(f, 0);
    };

    // Detect specific env
    if (isNode()) {
      // Node
      asap = function (f) {
        return process.nextTick(f);
      };
    } else if ((MutationObs = hasMutationObserver())) {
      // Modern browser
      asap = initMutationObserver(MutationObs);
    } else if (!capturedSetTimeout) {
      // vert.x
      // var vertxRequire = require;
      // var vertx = vertxRequire('vertx');
      var vertx = Function("return this")().require("vertx");
      setTimer = function (f, ms) {
        return vertx.setTimer(ms, f);
      };
      clearTimer = vertx.cancelTimer;
      asap = vertx.runOnLoop || vertx.runOnContext;
    }

    return {
      setTimer: setTimer,
      clearTimer: clearTimer,
      asap: asap,
    };

    function isNode() {
      return typeof process !== "undefined" && Object.prototype.toString.call(process) === "[object process]";
    }

    function hasMutationObserver() {
      return (
        (typeof MutationObserver !== "undefined" && MutationObserver) ||
        (typeof WebKitMutationObserver !== "undefined" && WebKitMutationObserver)
      );
    }

    function initMutationObserver(MutationObserver) {
      var scheduled;
      var node = document.createTextNode("");
      var o = new MutationObserver(run);
      o.observe(node, { characterData: true });

      function run() {
        var f = scheduled;
        scheduled = void 0;
        f();
      }

      var i = 0;
      return function (f) {
        scheduled = f;
        node.data = i ^= 1;
      };
    }
  });
})(
  typeof define === "function" && define.amd
    ? define
    : function (factory) {
        module.exports = factory(require);
      }
);
