var _ = require('lodash'),
    makeCache = require('teeny-cache'),
    createChooser = require('./string-chooser');

var collapseObjectKeys = (function () {
  
  function crawlObject (prefix, suffix, object, ret, config) {
    var modifiers = config.modifiers;
    _.each(object, function (i, key) {

      var value = object[key];

      if (_.isObject(value) && !_.isArray(value)) {
        // if (key is one of the config keywords) {
        if (modifiers.indexOf(key) >= 0) {
          crawlObject(prefix, suffix + '.' + key, value, ret, config);
        } else {
          crawlObject(prefix + key + '.', suffix, value, ret, config);
        }
      } else {
        ret[prefix + key + suffix] = value;
      }
    });
    return ret;
  }

  return function collapseObjectKeys (src, config, dest) {
    return crawlObject('', '', src, dest || {}, config);
  };
})();

var Map = function (options, config, initial) {
  this._chooser = createChooser(options, config);
  this._map = collapseObjectKeys(initial, config);
  this._valueCache = makeCache();
  this._initialKeys = _.keys(this._map);
};

_.extend(Map.prototype, {
  get: function (stem) {
    var self = this;
    return self._valueCache(
      stem, 
      function (stem) {
        var key = self._chooser(stem, self._initialKeys);
        return self._map[key];
      }
    );  
  },

});

module.exports = {
  Map: Map,
  collapse: collapseObjectKeys
};
@@ -916,22 +916,169 @@
 al) %7B%0A  
-this._
+var chooser, flatMap;%0A  if (arguments.length === 2) %7B%0A    chooser = options._chooser;%0A    flatMap = config;%0A    config = options._config;%0A  %7D else %7B%0A    
 chooser 
@@ -1113,23 +1113,23 @@
 fig);%0A  
-this._m
+  flatM
 ap = col
@@ -1162,16 +1162,95 @@
 onfig);%0A
+  %7D%0A  this._chooser = chooser;%0A  this._config = config;%0A  this._map = flatMap;%0A
   this._
@@ -1570,16 +1570,339 @@
  %0A  %7D,%0A%0A
+  mergeWith: function (that) %7B%0A    if (that._map) %7B%0A      return new Map(this, _.extend(%7B%7D, this._map, that._map));%0A    %7D else if (_.isObject(that)) %7B%0A      return new Map(this, _.extend(%7B%7D, this._map, collapseObjectKeys(that, this._config)));%0A    %7D%0A    throw new Error('Unsure what to do with merging with ' + that);%0A  %7D%0A%0A
 %7D);%0A%0Amod

Allow mergeable maps.