var assign = require('lodash.assign');
var toArray = require('lodash.toarray');

module.exports = Injector;

function Injector(injector) {
  this.dependencies = {};
  if (injector instanceof Injector) {
    this.mergeInjector(injector);
  }
}

Injector.prototype = {

  regDependency: function(name, dependency) {
    if (typeof name === 'object') {
      var self = this;
      Object.keys(name).forEach(function(key) {
        self.regDependency(key, name[key]);
      });
      return;
    }
    this.dependencies[name] = dependency;
  },

  getDependency: function(name) {
    return this.dependencies[name];
  },

  hasDependency: function(name) {
    return this.dependencies.hasOwnProperty(name);
  },

  getDependencies: function(fnArgs, defaultValues) {
    var self = this;
    defaultValues = defaultValues || {};
    if (!fnArgs) {
      return defaultValues;
    }

    return fnArgs.map(function(dependencyName, idx) {
      if (dependencyName && 'object' === typeof dependencyName) {
        var hashedDeps = {};
        Object.keys(dependencyName).forEach(function(depKey) {
          var depName = dependencyName[depKey];
          hashedDeps[depKey] = self.getDependency(depName);
        });
        return hashedDeps;
      } else if (dependencyName === null) {
        return defaultValues[idx];
      } else {
        return self.getDependency(dependencyName);
      }
    });
  },

  mergeInjector: function(otherInjector) {
    assign(this.dependencies, otherInjector.dependencies);
  },

  inject: function(fn, fnArgs) {
    var _fn = fn;
    var self = this;
    fn = function() {
      var defaultArgs = toArray(arguments);
      var injector = (this instanceof Injector ? this : (this.injector || self));
      var _args = injector.getDependencies(fnArgs, defaultArgs);
      return _fn.apply(this, _args);
    };
    return fn;
  }
};

@@ -1,12 +1,27 @@
+'use strict';%0A%0A
 var assign =
@@ -1673,55 +1673,168 @@
 var 
-injector = (this instanceof Injector ? this : (
+ctx;%0A      var injector;%0A%0A      if (this instanceof Injector) %7B%0A        ctx = 0;%0A        injector = this;%0A      %7D else %7B%0A        ctx = this;%0A        injector = 
 this
@@ -1854,11 +1854,17 @@
 self
-));
+;%0A      %7D
 %0A   
@@ -1948,20 +1948,19 @@
 n.apply(
-this
+ctx
 , _args)

Call function with immutable `this` when this is a injector