text: "use strict";
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
  
  exports.toErrorList = toErrorList;
  exports.default = validateFormData;
  
  var _lodash = require("lodash.topath");
  
  var _lodash2 = _interopRequireDefault(_lodash);
  
  var _jsonschema = require("jsonschema");
  
  var _utils = require("./utils");
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
  
  function toErrorSchema(errors) {
    // Transforms a jsonschema validation errors list:
    // [
    //   {property: "instance.level1.level2[2].level3", message: "err a"},
    //   {property: "instance.level1.level2[2].level3", message: "err b"},
    //   {property: "instance.level1.level2[4].level3", message: "err b"},
    // ]
    // Into an error tree:
    // {
    //   level1: {
    //     level2: {
    //       2: {level3: {errors: ["err a", "err b"]}},
    //       4: {level3: {errors: ["err b"]}},
    //     }
    //   }
    // };
    if (!errors.length) {
      return {};
    }
    return errors.reduce(function (errorSchema, error) {
      var property = error.property,
          message = error.message;
  
      var path = (0, _lodash2.default)(property);
      var parent = errorSchema;
      var _iteratorNormalCompletion = true;
      var _didIteratorError = false;
      var _iteratorError = undefined;
  
      try {
        for (var _iterator = path.slice(1)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
          var segment = _step.value;
  
          if (!(segment in parent)) {
            parent[segment] = {};
          }
          parent = parent[segment];
        }
      } catch (err) {
        _didIteratorError = true;
        _iteratorError = err;
      } finally {
        try {
          if (!_iteratorNormalCompletion && _iterator.return) {
            _iterator.return();
          }
        } finally {
          if (_didIteratorError) {
            throw _iteratorError;
          }
        }
      }
  
      if (Array.isArray(parent.__errors)) {
        // We store the list of errors for this node in a property named __errors
        // to avoid name collision with a possible sub schema field named
        // "errors" (see `validate.createErrorHandler`).
        parent.__errors = parent.__errors.concat(message);
      } else {
        parent.__errors = [message];
      }
      return errorSchema;
    }, {});
  }
  
  function toErrorList(errorSchema) {
    var fieldName = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "root";
  
    // XXX: We should transform fieldName as a full field path string.
    var errorList = [];
    if ("__errors" in errorSchema) {
      errorList = errorList.concat(errorSchema.__errors.map(function (stack) {
        return {
          stack: fieldName + ": " + stack
        };
      }));
    }
    return Object.keys(errorSchema).reduce(function (acc, key) {
      if (key !== "__errors") {
        acc = acc.concat(toErrorList(errorSchema[key], key));
      }
      return acc;
    }, errorList);
  }
  
  function createErrorHandler(formData) {
    var handler = {
      // We store the list of errors for this node in a property named __errors
      // to avoid name collision with a possible sub schema field named
      // "errors" (see `utils.toErrorSchema`).
      __errors: [],
      addError: function addError(message) {
        this.__errors.push(message);
      }
    };
    if ((0, _utils.isObject)(formData)) {
      return Object.keys(formData).reduce(function (acc, key) {
        return _extends({}, acc, _defineProperty({}, key, createErrorHandler(formData[key])));
      }, handler);
    }
    if (Array.isArray(formData)) {
      return formData.reduce(function (acc, value, key) {
        return _extends({}, acc, _defineProperty({}, key, createErrorHandler(value)));
      }, handler);
    }
    return handler;
  }
  
  function unwrapErrorHandler(errorHandler) {
    return Object.keys(errorHandler).reduce(function (acc, key) {
      if (key === "addError") {
        return acc;
      } else if (key === "__errors") {
        return _extends({}, acc, _defineProperty({}, key, errorHandler[key]));
      }
      return _extends({}, acc, _defineProperty({}, key, unwrapErrorHandler(errorHandler[key])));
    }, {});
  }
  
  /**
   * This function processes the formData with a user `validate` contributed
   * function, which receives the form data and an `errorHandler` object that
   * will be used to add custom validation errors for each field.
   */
  function validateFormData(formData, schema, customValidate, transformErrors) {
    var _jsonValidate = (0, _jsonschema.validate)(formData, schema),
        errors = _jsonValidate.errors;
  
    if (typeof transformErrors === "function") {
      errors = transformErrors(errors);
    }
    var errorSchema = toErrorSchema(errors);
  
    if (typeof customValidate !== "function") {
      return { errors: errors, errorSchema: errorSchema };
    }
  
    var errorHandler = customValidate(formData, createErrorHandler(formData));
    var userErrorSchema = unwrapErrorHandler(errorHandler);
    var newErrorSchema = (0, _utils.mergeObjects)(errorSchema, userErrorSchema, true);
    // XXX: The errors list produced is not fully compliant with the format
    // exposed by the jsonschema lib, which contains full field paths and other
    // properties.
    var newErrors = toErrorList(newErrorSchema);
  
    return { errors: newErrors, errorSchema: newErrorSchema };
  }