'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 _Factory = require('../factory/Factory');

var _Factory2 = _interopRequireDefault(_Factory);

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. Internal class
 *
 * Injects functions into objects. Used internally.
 * Not intended to be used on it's own.
 *
 * @static
 */
var Injector = function () {
  function Injector() {
    _classCallCheck(this, Injector);
  }

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

    /**
     * Appends a function after complete and remembers the original
     *
     * @param {Task} task task to be modified
     * @param {Function} callback function to be called after complete
     * @param {String} key map for the original callback
     * @return {Task} task modified task
     */
    value: function afterComplete(task, callback, key) {
      Injector.resetAfterComplete(task, key);

      var current = task._complete;

      Object.defineProperty(task, '__injected__' + key, {
        configurable: true,
        enumerable: true,
        value: current
      });

      task._complete = function (self) {
        for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
          args[_key - 1] = arguments[_key];
        }

        var error = void 0;
        try {
          if (current !== undefined) {
            current.apply(undefined, [self].concat(args));
          }
        } catch (e) {
          error = e;
        }
        callback.apply(undefined, [error, self].concat(args));
      };

      return task;
    }

    /**
     * Resets the complete method to it's original state
     *
     * @param {Task} task task to be modified
     * @param {String} key map for the original callback
     * @return {Task} task modified task
     */

  }, {
    key: 'resetAfterComplete',
    value: function resetAfterComplete(task, key) {
      var property = '__injected__' + key;
      if (task.hasOwnProperty(property)) {
        task._complete = task[property];
      }

      delete task['__injected__' + key];

      return task;
    }

    /**
     * Adds a method called chain to get Factory._CHAIN_
     *
     * Shortcut for task.get(Factory._CHAIN_)
     *
     * @param {Task} task task to be modified
     * @return {Task} task modified task
     */

  }, {
    key: 'addChainGetter',
    value: function addChainGetter(task) {
      Object.defineProperty(task, 'chain', {
        get: function get() {
          return this.get(_Factory2.default._CHAIN_);
        },
        configurable: true,
        enumerable: true
      });

      return task;
    }

    /**
     * Remove a method called chain to get Factory._CHAIN_
     *
     * @param {Task} task task to be modified
     * @return {Task} task modified task
     */

  }, {
    key: 'removeChainGetter',
    value: function removeChainGetter(task) {
      delete task.chain;

      return task;
    }
  }]);

  return Injector;
}();

exports.default = Injector;