var R = require('ramda')
var fa = require('fluent-arguments')

function getConstructorInstanceWithArgs (Constructor, constructorArgs) {
  return new (Function.prototype.bind.apply(Constructor, [ null ].concat(Array.prototype.slice.call(constructorArgs))))()
}

function getArrayFromArrayLikeObject (args) {
  return Array.prototype.slice.call(args)
}

var isMethod = R.curry(function (object, propName) {
  return !Object.getOwnPropertyDescriptor(object, propName).get &&
    typeof object[ propName ] === 'function' && !(propName === 'constructor')
})

var applyToEachFunctionKeyInObject = function (appliedFunction, object) {
  R.compose(
    R.forEach(appliedFunction),
    R.filter(isMethod(object))
  )(Object.getOwnPropertyNames(object))
}

var applyToEachFunctionKeyInPrototypeChain = function (appliedFunction, object) {
  if (object) {
    applyToEachFunctionKeyInObject(appliedFunction, object)
    applyToEachFunctionKeyInPrototypeChain(appliedFunction, Object.getPrototypeOf(object))
  }
}

var getInstanceIndexWithValidation = function (index, numInstances) {
  var instanceIndex = index || 0

  if (typeof index === 'undefined') {
    if (numInstances > 1) {
      throw new Error('Tried to access only instance of StubConstructor, but there were ' +
        numInstances + ' instances.')
    }
  }
  if (numInstances <= instanceIndex) {
    throw new Error('Tried to access StubConstructor instance ' + instanceIndex + ', but there were only ' +
      numInstances + ' instances.')
  }
  return instanceIndex
}

module.exports = function getStubOrSpyConstructor (getConstructorProperties) {
  return function (Target) {
    var constructorProps = getConstructorProperties(Target)
    var instances = []
    var instanceArgs = []
    var methodParams = []
    var afterCreation

    function StubOrSpyConstructor () {
      var instance = getConstructorInstanceWithArgs(constructorProps.SourceConstructor, arguments)
      instanceArgs.push(getArrayFromArrayLikeObject(arguments))
      instances.push(instance)

      Target && applyToEachFunctionKeyInPrototypeChain(
        constructorProps.processMethodOfInstance(instance), constructorProps.getInstanceMethodNameSource(instance))
      methodParams.forEach(constructorProps.configureMethodOfInstance(instance))
      afterCreation && afterCreation(instance)
      return instance
    }

    StubOrSpyConstructor.prototype = constructorProps.SourceConstructor.prototype

    function configureMethods (methods) {
      methodParams = methods
      return this
    }

    StubOrSpyConstructor[ constructorProps.configureMethodsKey ] = fa.createFunc(configureMethods)

    StubOrSpyConstructor.afterCreation = function (onAfterCreation) {
      afterCreation = onAfterCreation
      return this
    }

    StubOrSpyConstructor.getInstances = function () {
      return instances
    }

    StubOrSpyConstructor.getInstance = function (index) {
      return instances[ getInstanceIndexWithValidation(index, instances.length) ]
    }

    StubOrSpyConstructor.getInstancesArgs = function () {
      return instanceArgs
    }

    StubOrSpyConstructor.getInstanceArgs = function (index) {
      return instanceArgs[ getInstanceIndexWithValidation(index, instances.length) ]
    }

    Target && applyToEachFunctionKeyInObject(constructorProps.processMethodOfConstructor(StubOrSpyConstructor), Target)
    return StubOrSpyConstructor
  }
}

@@ -60,206 +60,8 @@
 ')%0A%0A
-function getConstructorInstanceWithArgs (Constructor, constructorArgs) %7B%0A  return new (Function.prototype.bind.apply(Constructor, %5B null %5D.concat(Array.prototype.slice.call(constructorArgs))))()%0A%7D%0A%0A
 func
@@ -1637,54 +1637,8 @@
     
-var instance = getConstructorInstanceWithArgs(
 cons
@@ -1667,16 +1667,27 @@
 structor
+.apply(this
 , argume
@@ -1776,24 +1776,20 @@
 es.push(
-instance
+this
 )%0A%0A     
@@ -1888,24 +1888,20 @@
 nstance(
-instance
+this
 ), const
@@ -1940,24 +1940,20 @@
 eSource(
-instance
+this
 ))%0A     
@@ -2017,24 +2017,20 @@
 nstance(
-instance
+this
 ))%0A     
@@ -2061,24 +2061,20 @@
 reation(
-instance
+this
 )%0A      
@@ -2080,24 +2080,20 @@
  return 
-instance
+this
 %0A    %7D%0A%0A

Change instance creation to be more compatible with Angular