import _ from 'lodash'

export const getPropType = (prop, attr) => {
  return prop.iterable
    ? recursiveValues(prop, attr)
    : prop[attr]
}

export const recursiveObject = (values, attr) => {
  return _.reduce(values, (memo, prop, key) => Object.assign({
    [key]: getPropType(prop, attr)
  }, memo), {})
}

export const recursiveArray = (values, attr) => {
  return _.map(values, (prop) => {
    return getPropType(prop, attr)
  })
}

export const selectRecursiveStrategy = (values, attr) => {
  return _.isArray(values)
    ? recursiveArray(values, attr)
    : recursiveObject(values, attr)
}

export const recursiveValues = ({ type, values }, attr) => {
  const exec = attr === 'type' ? type : _.identity
  return exec(selectRecursiveStrategy(values, attr))
}

export const createPropTypes = (definition) => {
  return recursiveObject(definition, 'type')
}

export const createDefault = (definition) => {
  return recursiveObject(definition, 'default')
}

export const filterByKeys = (definition, candidate) => {
  const keys = _.intersection(_.keys(definition), _.keys(candidate))
  return _.pick(candidate, keys)
}

export const transform = (definition, candidate, mutators) => Object.assign(
  filterByKeys(definition, candidate),
  _.reduce(mutators, (memo, value, key) => Object.assign({
    [key]: _.isFunction(value) ? value(candidate) : value,
    memo
  }), {})
)

@@ -1116,24 +1116,48 @@
 e, keys)%0A%7D%0A%0A
+let protoMutators = %7B%7D%0A%0A
 export const
@@ -1201,20 +1201,47 @@
 mutators
-) =%3E
+ = protoMutators) =%3E %7B%0A  return
  Object.
@@ -1248,16 +1248,18 @@
 assign(%0A
+  
   filter
@@ -1291,16 +1291,18 @@
 ate),%0A  
+ 
+ 
 _.reduce
@@ -1342,32 +1342,34 @@
 Object.assign(%7B%0A
+  
     %5Bkey%5D: _.isF
@@ -1413,27 +1413,164 @@
 alue
-,
 %0A   
+ %7D,
  memo
-%0A  %7D
 ), %7B%7D)%0A
+  )%0A%7D%0A%0AObject.defineProperty(transform, 'mutators', %7B%0A  get: () =%3E protoMutators,%0A  set: (mutators) =%3E %7B%0A    protoMutators = mutators%0A  %7D%0A%7D
 )%0A

Add proto mutators on transform