(function() {
  var checkValueAtKeyPath, deepClone, deepDefaults, isPlainObject, splitKeyPath;

  splitKeyPath = require('key-path-helpers').splitKeyPath;

  isPlainObject = function(value) {
    return (value != null ? value.constructor : void 0) === Object;
  };

  checkValueAtKeyPath = function(object, keyPath) {
    var key, _i, _len, _ref;
    _ref = splitKeyPath(keyPath);
    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
      key = _ref[_i];
      if (isPlainObject(object)) {
        if (object.hasOwnProperty(key)) {
          object = object[key];
        } else {
          return [void 0, false];
        }
      } else {
        return [void 0, true];
      }
    }
    return [object, true];
  };

  deepDefaults = function(target, defaults) {
    var key, _i, _len, _ref;
    if (isPlainObject(target) && isPlainObject(defaults)) {
      _ref = Object.keys(defaults);
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        key = _ref[_i];
        if (target.hasOwnProperty(key)) {
          deepDefaults(target[key], defaults[key]);
        } else {
          target[key] = defaults[key];
        }
      }
    }
  };

  deepClone = function(value) {
    var key, result, _i, _len, _ref;
    if (Array.isArray(value)) {
      return value.map(function(element) {
        return deepClone(element);
      });
    } else if (isPlainObject(value)) {
      result = {};
      _ref = Object.keys(value);
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        key = _ref[_i];
        result[key] = deepClone(value[key]);
      }
      return result;
    } else {
      return value;
    }
  };

  module.exports = {
    isPlainObject: isPlainObject,
    checkValueAtKeyPath: checkValueAtKeyPath,
    deepClone: deepClone,
    deepDefaults: deepDefaults
  };

}).call(this);
