(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.methodinjector = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.mrem = exports.mres = exports.minjAfter = exports.minjBefore = exports.minj = exports.Injector = undefined;

var _Injector = require('./injector/Injector');

var _Injector2 = _interopRequireDefault(_Injector);

var _minj = require('./injector/minj');

var _minj2 = _interopRequireDefault(_minj);

var _minjBefore = require('./injector/minjBefore');

var _minjBefore2 = _interopRequireDefault(_minjBefore);

var _minjAfter = require('./injector/minjAfter');

var _minjAfter2 = _interopRequireDefault(_minjAfter);

var _mres = require('./injector/mres');

var _mres2 = _interopRequireDefault(_mres);

var _mrem = require('./injector/mrem');

var _mrem2 = _interopRequireDefault(_mrem);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

exports.Injector = _Injector2.default;
exports.minj = _minj2.default;
exports.minjBefore = _minjBefore2.default;
exports.minjAfter = _minjAfter2.default;
exports.mres = _mres2.default;
exports.mrem = _mrem2.default;
},{"./injector/Injector":2,"./injector/minj":3,"./injector/minjAfter":4,"./injector/minjBefore":5,"./injector/mrem":6,"./injector/mres":7}],2:[function(require,module,exports){
'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _Launcher = require('../types/Launcher');

var _Launcher2 = _interopRequireDefault(_Launcher);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * Injector
 *
 * Contains inject and cleanup methods
 *
 * @static
 */
var Injector = function () {
  function Injector() {
    _classCallCheck(this, Injector);
  }

  _createClass(Injector, null, [{
    key: 'injectBefore',


    /**
     * Inject before
     *
     * @param {Function} method original method or launch method
     * @param {Function} inject inject method
     * @return {Function} launch launch method
     * @static
     */


    /**
     * Predefined inject after
     *
     * @param {int} INJECT_AFTER predefined value
     * @static
     */
    value: function injectBefore(method, inject) {
      return Injector.inject(method, inject, Injector.INJECT_BEFORE);
    }

    /**
     * Inject after
     *
     * @param {Function} method original method or launch method
     * @param {Function} inject inject method
     * @return {Function} launch launch method
     * @static
     */


    /**
     * All launchers
     *
     * @param {Array<Launcher>} _launchers all launchers
     * @static
     * @private
     */

    /**
     * Predefined inject before
     *
     * @param {int} INJECT_BEFORE predefined value
     * @static
     */

  }, {
    key: 'injectAfter',
    value: function injectAfter(method, inject) {
      return Injector.inject(method, inject, Injector.INJECT_AFTER);
    }

    /**
     * Inject before or after
     *
     * @param {Function} method original method or launch method
     * @param {Function} inject inject method
     * @param {int} beforeOrAfter 0 - before, 1 - is after
     * @return {Function} launch launch method
     * @static
     */

  }, {
    key: 'inject',
    value: function inject(method, _inject) {
      var beforeOrAfter = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;

      var launcher = Injector._toLauncher(method);
      var collection = beforeOrAfter === Injector.INJECT_BEFORE ? launcher.before : beforeOrAfter === Injector.INJECT_AFTER ? launcher.after : [];
      collection.push(_inject);
      return launcher.launch;
    }

    /**
     * Remove injection
     *
     * @param {Function} launch method
     * @param {Function} inject inject method
     * @return {Function} launch launch method
     * @static
     */

  }, {
    key: 'remove',
    value: function remove(method, _remove) {
      var launcher = Injector._toLauncher(method);
      if (launcher.before.indexOf(_remove) !== -1) {
        launcher.before.splice(launcher.before.indexOf(_remove), 1);
      } else if (launcher.after.indexOf(_remove) !== -1) {
        launcher.after.splice(launcher.after.indexOf(_remove), 1);
      }
      return method;
    }

    /**
     * Resets launch and all injections
     *
     * @param {Function} launch launch method
     * @return {Function} original original method
     * @static
     */

  }, {
    key: 'reset',
    value: function reset(method) {
      var launcher = Injector._locate(method);
      if (launcher !== undefined) {
        Injector._launchers.splice(Injector._launchers.indexOf(launcher), 1);
        return launcher.original;
      } else {
        return method;
      }
    }

    /**
     * Converts original to launch
     *
     * @param {Function} method original method or launch method
     * @return {Launcher} launcher launcher
     * @static
     * @protected
     */

  }, {
    key: '_toLauncher',
    value: function _toLauncher(method) {
      var located = Injector._locate(method);
      if (located === undefined) {
        var launcher = new _Launcher2.default(method);
        Injector._launchers.push(launcher);
        return launcher;
      } else {
        return located;
      }
    }

    /**
     * Locates launcher by launch method
     *
     * @param {Function} method launch method
     * @return {Launcher} launcher launcher
     * @static
     * @protected
     */

  }, {
    key: '_locate',
    value: function _locate(method) {
      var launchers = Injector._launchers;
      var length = launchers.length;
      var located = undefined;
      for (var i = 0; i < length; ++i) {
        if (launchers[i].launch === method) {
          located = launchers[i];
          break;
        }
      }
      return located;
    }
  }]);

  return Injector;
}();

Injector.INJECT_BEFORE = 0;
Injector.INJECT_AFTER = 1;
Injector._launchers = [];
exports.default = Injector;
},{"../types/Launcher":8}],3:[function(require,module,exports){
'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _Injector = require('./Injector');

var _Injector2 = _interopRequireDefault(_Injector);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

exports.default = function () {
  return _Injector2.default.inject.apply(_Injector2.default, arguments);
};
},{"./Injector":2}],4:[function(require,module,exports){
'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _Injector = require('./Injector');

var _Injector2 = _interopRequireDefault(_Injector);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

exports.default = function () {
  return _Injector2.default.injectAfter.apply(_Injector2.default, arguments);
};
},{"./Injector":2}],5:[function(require,module,exports){
'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _Injector = require('./Injector');

var _Injector2 = _interopRequireDefault(_Injector);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

exports.default = function () {
  return _Injector2.default.injectBefore.apply(_Injector2.default, arguments);
};
},{"./Injector":2}],6:[function(require,module,exports){
'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _Injector = require('./Injector');

var _Injector2 = _interopRequireDefault(_Injector);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

exports.default = function () {
  return _Injector2.default.remove.apply(_Injector2.default, arguments);
};
},{"./Injector":2}],7:[function(require,module,exports){
'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _Injector = require('./Injector');

var _Injector2 = _interopRequireDefault(_Injector);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

exports.default = function () {
  return _Injector2.default.reset.apply(_Injector2.default, arguments);
};
},{"./Injector":2}],8:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * Launcher
 *
 * Launcher class. Keeps original method and injections.
 *
 * @param {Function} original original function
 */
var Launcher = function () {
  /**
   * Task constructor
   *
   * @param {Function} original original function
   */
  function Launcher(original) {
    _classCallCheck(this, Launcher);

    this.original = original;
    this.before = [];
    this.after = [];

    this.launch = this.launch.bind(this);
  }

  /**
   * Launches
   *
   * Runs the original function and all the injections.
   * Tries to combine arguments and keeps the changes
   *
   * @param {any} any any arguments
   * @return {any} any any result from original function
   */


  _createClass(Launcher, [{
    key: "launch",
    value: function launch() {
      for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
        args[_key] = arguments[_key];
      }

      var result = undefined;
      this.before.forEach(function (callback) {
        var result = callback.apply(undefined, _toConsumableArray(args));
        args = result !== undefined ? result : args;
      });
      if (this.original !== undefined) {
        result = this.original.apply(this, _toConsumableArray(args));
      }
      this.after.forEach(function (callback) {
        var result = callback.apply(undefined, _toConsumableArray(args));
        args = result !== undefined ? result : args;
      });
      return result;
    }
  }]);

  return Launcher;
}();

exports.default = Launcher;
},{}]},{},[1])(1)
});