import _defineProperty from "@babel/runtime/helpers/defineProperty";
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
import { validator } from '@atlaskit/adf-utils/validator';
import { ACTION_SUBJECT_ID } from '../analytics';
export var UNSUPPORTED_NODE_ATTRIBUTE = 'unsupportedNodeAttribute';
import { fireUnsupportedEvent } from './track-unsupported-content';
import { wrapWithUnsupported } from './wrapWithUnsupported';
var errorCallbackFor = function errorCallbackFor(marks, validate, dispatchAnalyticsEvent, validationOverrides) {
  return function (entity, error, options) {
    return validationErrorHandler(entity, error, _objectSpread(_objectSpread({}, options), {}, {
      allowNestedTables: validationOverrides === null || validationOverrides === void 0 ? void 0 : validationOverrides.allowNestedTables,
      allowTableInPanel: validationOverrides === null || validationOverrides === void 0 ? void 0 : validationOverrides.allowTableInPanel
    }), marks, validate, dispatchAnalyticsEvent);
  };
};
export var validationErrorHandler = function validationErrorHandler(entity, error, options, marks, validate, dispatchAnalyticsEvent) {
  if (entity && entity.type === UNSUPPORTED_NODE_ATTRIBUTE) {
    return entity;
  }
  if (options.isMark) {
    return wrapWithUnsupported(error.meta, 'mark');
  }
  if (options.isNodeAttribute) {
    var entityType = entity && entity.type ? entity.type : undefined;
    return {
      type: UNSUPPORTED_NODE_ATTRIBUTE,
      attrs: {
        type: {
          nodeType: entityType
        },
        unsupported: error.meta
      }
    };
  }
  if (entity && marks.indexOf(entity.type) > -1) {
    return;
  }

  /**
   * There's a inconsistency between ProseMirror and ADF.
   * `content` is actually optional in ProseMirror.
   * And, also empty `text` node is not valid.
   */
  if (error.code === 'MISSING_PROPERTIES' && entity.type === 'paragraph') {
    return {
      type: 'paragraph',
      content: []
    };
  }

  // Ignored via go/ees007
  // eslint-disable-next-line @atlaskit/editor/enforce-todo-comment-format
  // TODO: We can repair missing content like `panel` without a `paragraph`.
  if (error.code === 'INVALID_CONTENT_LENGTH') {
    if (error.meta && options.allowUnsupportedBlock && entity.content) {
      return getEntityForInvalidContentLength(error, entity, validate, marks, dispatchAnalyticsEvent);
    } else {
      // Can't fix it by wrapping
      if (dispatchAnalyticsEvent) {
        trackValidationError(dispatchAnalyticsEvent, error, entity);
      }
    }
  }

  // Nested tables don't actually exist in ADF. In ADF they are stored as an `extension` node with the nested table content serialized in a property of that extension.
  // Usually when we validate ADF we are validating this `extension` and then later transforming it into nested tables for usage by ProseMirror.
  // Under certain circumstances however, ADF validation is performed on this already transformed extension and since nested tables aren't allowed by ADF this
  // produces an error. For example, nested renderers in Confluence `bodiedExtension`'s. The nested renderer receives the already transformed nested tables that originated from the
  // `extension` node and validates it. This is invalid ADF so an error is thrown.
  // This override allows an exception to be made for nested tables in the validator in this circumstance.
  if (options.allowNestedTables) {
    var meta = error.meta;
    if (options.allowNestedTables && meta !== null && meta !== void 0 && meta.parentType && ['tableCell', 'tableHeader'].includes(meta === null || meta === void 0 ? void 0 : meta.parentType) && error.code === 'INVALID_CONTENT' && entity.type === 'table') {
      return entity;
    }
  }

  // panel_c1 is a ProseMirror-only variant: on save, table-in-panel documents are stored as
  // plain ADF `panel` nodes containing a `table`. The base validator-spec does not permit
  // `table` inside `panel` (it's gated behind the experiment), so we suppress the
  // INVALID_CONTENT error when the experiment is active.
  if (options.allowTableInPanel) {
    var _meta = error.meta;
    if ((_meta === null || _meta === void 0 ? void 0 : _meta.parentType) === 'panel' && error.code === 'INVALID_CONTENT' && entity.type === 'table') {
      return entity;
    }
  }
  if (options.allowUnsupportedBlock) {
    return wrapWithUnsupported(entity);
  }
  if (options.allowUnsupportedInline) {
    return wrapWithUnsupported(entity, 'inline');
  }
  if (dispatchAnalyticsEvent) {
    trackValidationError(dispatchAnalyticsEvent, error, entity);
  }
  return entity;
};
function getEntityForInvalidContentLength(error, entity, validate, marks, dispatchAnalyticsEvent) {
  var meta = error.meta;
  if (meta.type === 'maximum') {
    // Ignored via go/ees005
    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
    entity.content = entity.content.filter(function (x) {
      return !!x;
    }).map(function (child, index) {
      return index >= meta.requiredLength && child.type !== 'unsupportedBlock' ? wrapWithUnsupported(child) : validate(child, errorCallbackFor(marks, validate, dispatchAnalyticsEvent)).entity;
    });
  }
  if (meta.type === 'minimum') {
    // Ignored via go/ees005
    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
    if (entity.content.length === 0) {
      return wrapWithUnsupported(entity);
    }
    // Ignored via go/ees005
    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
    entity.content = entity.content.filter(function (x) {
      return !!x;
    }).map(function (child) {
      return child.type !== 'unsupportedBlock' ? wrapWithUnsupported(child) : child;
    });
  }
  return entity;
}
function trackValidationError(dispatchAnalyticsEvent, error, entity) {
  if (!dispatchAnalyticsEvent) {
    return;
  }
  fireUnsupportedEvent(dispatchAnalyticsEvent, ACTION_SUBJECT_ID.UNSUPPORTED_ERROR, {
    type: entity.type || '',
    ancestry: entity.ancestorHierarchy || '',
    parentType: entity.parentType || '',
    marks: entity.marks || [],
    attrs: entity.attrs || {}
  }, error.code);
}
export var validateADFEntity = function validateADFEntity(schema, node, dispatchAnalyticsEvent, validationOverrides) {
  var nodes = Object.keys(schema.nodes);
  var marks = Object.keys(schema.marks);
  var validate = validator(nodes, marks, {
    allowPrivateAttributes: true
  });
  var emptyDoc = {
    type: 'doc',
    content: []
  };
  var _validate = validate(node, errorCallbackFor(marks, validate, dispatchAnalyticsEvent, validationOverrides)),
    _validate$entity = _validate.entity,
    entity = _validate$entity === void 0 ? emptyDoc : _validate$entity;
  return entity;
};
// eslint-disable-next-line @atlaskit/editor/no-re-export
export { wrapWithUnsupported } from './wrapWithUnsupported';