// Generated by CoffeeScript 2.5.0
(function() {
  var isArray, pass;

  ({isArray} = require("util"));

  pass = {};

  module.exports = function({customMerge} = {}) {
    var initialize, merge, merge0, reducer, shallowCopy;
    shallowCopy = function(thing) {
      var key, o, value;
      switch (false) {
        case !isArray(thing):
          return [...thing];
        case !(thing instanceof Object):
          o = {};
          for (key in thing) {
            value = thing[key];
            o[key] = value;
          }
          return o;
        default:
          return thing;
      }
    };
    initialize = function(last) {
      switch (false) {
        case !isArray(last):
          return [];
        case !(last instanceof Object):
          return {};
        default:
          return last;
      }
    };
    merge = function(lhs, rhs, output0, inplace = false) {
      var decission;
      if (customMerge) {
        decission = customMerge(lhs, rhs, pass);
        if (decission === pass) {
          return merge0(lhs, rhs, output0, inplace);
        } else {
          return decission;
        }
      } else {
        return merge0(lhs, rhs, output0, inplace);
      }
    };
    merge0 = function(lhs, rhs, output0, inplace = false) {
      var key, output, value;
      switch (false) {
        case !(lhs == null):
          return rhs;
        case rhs !== null:
          return rhs;
        case !(rhs == null):
          return lhs;
        case !!(rhs instanceof Object):
          return rhs;
        case !!(lhs instanceof Object):
          return rhs;
        case !(lhs.constructor !== Object || rhs.constructor !== Object):
          return rhs;
        case !(isArray(rhs) || isArray(lhs)):
          return rhs;
        default:
          output = inplace || (output0 !== lhs) ? output0 : shallowCopy(output0);
          for (key in rhs) {
            value = rhs[key];
            output[key] = merge(output[key], value, output[key], inplace);
          }
          return output;
      }
    };
    reducer = function({
        data: lhs,
        inplace
      }, rhs) {
      var output;
      output = merge(lhs, rhs, lhs, inplace);
      return {
        data: output,
        inplace: inplace || (output !== lhs) && (output !== rhs)
      };
    };
    return function(...args) {
      var data;
      ({data} = args.reduce(reducer, {
        inplace: false
      }));
      return data;
    };
  };

}).call(this);
