import _ from 'lodash'

function request() {
  return function() {
    throw new Error('rest.map.req is not implemented')
  }
}

function response(map, spec = {}) {
  const {expand} = spec

  function mapFields(document, map, expand) {
    const doc = {}

    if (_.isFunction(document.toObject)) {
      document = document.toObject()
    }

    _.forEach(document, function(val, key) {
      key = map[key] || key
      doc[key] = val
    })

    // expand
    _.forEach(expand, function(map, path) {
      if (_.isArray(doc[path])) {
        doc[path] = _.map(doc[path], function(document) {
          return mapFields(document, map)
        })
        return
      }

      if (_.isObject(doc[path])) {
        doc[path] = mapFields(doc[path], map)
      }
    })

    return doc
  }

  return function(req, res) {
    let queryExpand
    // property expansion
    if (_.isString(req.query.expand)) {
      queryExpand = req.query.expand.split(',')
    }
    let expandedPaths = _.pick(expand, queryExpand)

    if (_.isArray(res.body)) {
      res.body = _.map(res.body, function(document) {
        return mapFields(document, map, expandedPaths)
      })
      return
    }

    if (_.isObject(res.body)) {
      res.body = mapFields(res.body, map, expandedPaths)
    }
  }

}

export default Object.freeze({
  req: request,
  res: response
})

@@ -44,82 +44,1116 @@
 %7B%0A  
-return function() %7B%0A    throw new Error('rest.map.req is not implemented')
+const %7Bexpand%7D = spec%0A%0A  function mapFields(document, map, expand) %7B%0A    const doc = %7B%7D%0A%0A    if (_.isFunction(document.toObject)) %7B%0A      document = document.toObject()%0A    %7D%0A%0A    _.forEach(document, function(val, key) %7B%0A      key = map%5Bkey%5D %7C%7C key%0A      doc%5Bkey%5D = val%0A    %7D)%0A%0A    // expand%0A    _.forEach(expand, function(map, path) %7B%0A      if (_.isArray(doc%5Bpath%5D)) %7B%0A        doc%5Bpath%5D = _.map(doc%5Bpath%5D, function(document) %7B%0A          return mapFields(document, map)%0A        %7D)%0A        return%0A      %7D%0A%0A      if (_.isObject(doc%5Bpath%5D)) %7B%0A        doc%5Bpath%5D = mapFields(doc%5Bpath%5D, map)%0A      %7D%0A    %7D)%0A%0A    return doc%0A  %7D%0A%0A  return function(req, res) %7B%0A    let queryExpand%0A    // property expansion%0A    if (_.isString(req.query.expand)) %7B%0A      queryExpand = req.query.expand.split(',')%0A    %7D%0A    let expandedPaths = _.pick(expand, queryExpand)%0A%0A    if (_.isArray(req.body)) %7B%0A      req.body = _.map(req.body, function(document) %7B%0A        return mapFields(document, map, expandedPaths)%0A      %7D)%0A      return%0A    %7D%0A%0A    if (_.isObject(req.body)) %7B%0A      req.body = mapFields(req.body, map, expandedPaths)%0A    %7D
 %0A  %7D

add mapping for request body