'use strict';

function PromiseWrap() {}

module.exports = function patchPromise() {
  const hooks = this._hooks;
  const state = this._state;

  const Promise = global.Promise;

  /* As per ECMAScript 2015, .catch must be implemented by calling .then, as
   * such we need needn't patch .catch as well. see:
   * http://www.ecma-international.org/ecma-262/6.0/#sec-promise.prototype.catch
   */
  const oldThen = Promise.prototype.then;
  Promise.prototype.then = wrappedThen;

  function makeWrappedHandler(fn, handle, uid) {
    if ('function' !== typeof fn) return fn;

    return function wrappedHandler() {
      hooks.pre.call(handle);
      try {
        return fn.apply(this, arguments);
      } finally {
        hooks.post.call(handle);
        hooks.destroy.call(null, uid);
      }
    };
  }

  function wrappedThen(onFulfilled, onRejected) {
    if (!state.enabled) return oldThen.call(this, onFulfilled, onRejected);

    const handle = new PromiseWrap();
    const uid = --state.counter;

    hooks.init.call(handle, 0, uid, null);

    return oldThen.call(
      this,
      makeWrappedHandler(onFulfilled, handle, uid),
      makeWrappedHandler(onRejected, handle, uid)
    );
  }
};

@@ -517,16 +517,31 @@
 dle, uid
+, isOnFulfilled
 ) %7B%0A    
@@ -574,18 +574,134 @@
 fn) 
-return fn;
+%7B%0A      return isOnFulfilled%0A        ? makeUnhandledResolutionHandler(uid)%0A        : makeUnhandledRejectionHandler(uid);%0A    %7D
 %0A%0A  
@@ -931,16 +931,352 @@
 %7D;%0A  %7D%0A%0A
+  function makeUnhandledResolutionHandler(uid) %7B%0A    return function unhandledResolutionHandler(val) %7B%0A      hooks.destroy.call(null, uid);%0A      return val;%0A    %7D;%0A  %7D%0A%0A  function makeUnhandledRejectionHandler(uid) %7B%0A    return function unhandledRejectedHandler(val) %7B%0A      hooks.destroy.call(null, uid);%0A      throw val;%0A    %7D;%0A  %7D%0A%0A
   functi
@@ -1596,16 +1596,22 @@
 dle, uid
+, true
 ),%0A     
@@ -1653,16 +1653,23 @@
 dle, uid
+, false
 )%0A    );

add handlers for unhandled paths in order to emit destroy