(function() {
  var isPlainObject, plus, splitKeyPath

  splitKeyPath = function(keyPath) {
    var char, i, keyPathArray, startIndex, _i, _len;
    startIndex = 0;
    keyPathArray = [];
    if (keyPath == null) {
      return keyPathArray;
    }
    for (i = _i = 0, _len = keyPath.length; _i < _len; i = ++_i) {
      char = keyPath[i];
      if (char === '.' && (i === 0 || keyPath[i - 1] !== '\\')) {
        keyPathArray.push(keyPath.substring(startIndex, i));
        startIndex = i + 1;
      }
    }
    keyPathArray.push(keyPath.substr(startIndex, keyPath.length));
    return keyPathArray;
  };
  isPlainObject = function(value) {
    return _.isObject(value) && !_.isArray(value);
  };

  plus = {
    mapObject: function(object, iterator) {
      var key, newObject, value, _i, _len, _ref, _ref1;
      newObject = {};
      _ref = Object.keys(object);
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        key = _ref[_i];
        _ref1 = iterator(key, object[key]), key = _ref1[0], value = _ref1[1];
        newObject[key] = value;
      }
      return newObject;
    },
    remove: function(array, element) {
      var index;
      index = array.indexOf(element);
      if (index >= 0) {
        array.splice(index, 1);
      }
      return array;
    },
    deepClone: function(object) {
      if (_.isArray(object)) {
        return object.map(function(value) {
          return plus.deepClone(value);
        });
      } else if (_.isObject(object) && !_.isFunction(object)) {
        return plus.mapObject(object, (function(_this) {
          return function(key, value) {
            return [key, plus.deepClone(value)];
          };
        })(this));
      } else {
        return object;
      }
    },
    deepExtend: function(target) {
      var i, key, object, result, _i, _len, _ref;
      result = target;
      i = 0;
      while (++i < arguments.length) {
        object = arguments[i];
        if (isPlainObject(result) && isPlainObject(object)) {
          _ref = Object.keys(object);
          for (_i = 0, _len = _ref.length; _i < _len; _i++) {
            key = _ref[_i];
            result[key] = plus.deepExtend(result[key], object[key]);
          }
        } else {
          result = plus.deepClone(object);
        }
      }
      return result;
    },
    valueForKeyPath: function(object, keyPath) {
      var key, keys, _i, _len;
      keys = splitKeyPath(keyPath);
      for (_i = 0, _len = keys.length; _i < _len; _i++) {
        key = keys[_i];
        object = object[key];
        if (object == null) {
          return;
        }
      }
      return object;
    },
    setValueForKeyPath: function(object, keyPath, value) {
      var key, keys;
      keys = splitKeyPath(keyPath);
      while (keys.length > 1) {
        key = keys.shift();
        if (object[key] == null) {
          object[key] = {};
        }
        object = object[key];
      }
      if (value != null) {
        return object[keys.shift()] = value;
      } else {
        return delete object[keys.shift()];
      }
    }
  }

  module.exports = plus

}).call(this)
