import { syncBlockFallbackTransform, transformDedupeMarks, transformIndentationMarks, transformInvalidMediaContent, transformMediaLinkMarks, transformNestedTablesIncomingDocument, transformNodesMissingContent, transformTextLinkCodeMarks, transformMediaSingleWidth, transformContainerNodes } from '@atlaskit/adf-utils/transforms';
import { Node } from '@atlaskit/editor-prosemirror/model';
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
import { ACTION, ACTION_SUBJECT, EVENT_TYPE } from '../analytics';
import { isNestedTablesSupported } from '../nesting/isNestedTablesSupported';
import { isPanelNestingTableSupported } from '../nesting/isPanelNestingTableSupported';
import { sanitizeNodeForPrivacy } from './filter/privacy-filter';
import { findAndTrackUnsupportedContentNodes } from './track-unsupported-content';
import { validateADFEntity } from './validate-using-spec';
var transformNestedTablesWithAnalytics = function transformNestedTablesWithAnalytics(node, dispatchAnalyticsEvent) {
  try {
    var _transformNestedTable = transformNestedTablesIncomingDocument(node),
      transformedAdf = _transformNestedTable.transformedAdf,
      isTransformed = _transformNestedTable.isTransformed;
    if (isTransformed) {
      if (dispatchAnalyticsEvent) {
        dispatchAnalyticsEvent({
          action: ACTION.NESTED_TABLE_TRANSFORMED,
          actionSubject: ACTION_SUBJECT.EDITOR,
          eventType: EVENT_TYPE.OPERATIONAL
        });
      }
      return {
        transformedAdf: transformedAdf,
        isTransformed: isTransformed
      };
    }
  } catch (e) {
    // eslint-disable-next-line no-console
    console.error('Failed to transform one or more nested tables in the document');
    if (dispatchAnalyticsEvent) {
      dispatchAnalyticsEvent({
        action: ACTION.DOCUMENT_PROCESSING_ERROR,
        actionSubject: ACTION_SUBJECT.EDITOR,
        eventType: EVENT_TYPE.OPERATIONAL,
        attributes: {
          errorMessage: "".concat(e instanceof Error && e.name === 'NodeNestingTransformError' ? 'NodeNestingTransformError - Failed to transform one or more nested tables' : undefined)
        }
      });
    }
  }
  return {
    transformedAdf: node,
    isTransformed: false
  };
};
var transformContainerNodesWithAnalytics = function transformContainerNodesWithAnalytics(node, schema, dispatchAnalyticsEvent) {
  try {
    var _transformContainerNo = transformContainerNodes(node, schema),
      transformedAdf = _transformContainerNo.transformedAdf,
      isTransformed = _transformContainerNo.isTransformed,
      transformedNodeTypes = _transformContainerNo.transformedNodeTypes;
    if (isTransformed && transformedAdf) {
      if (dispatchAnalyticsEvent) {
        dispatchAnalyticsEvent({
          action: ACTION.CONTAINER_NODE_TRANSFORMED,
          actionSubject: ACTION_SUBJECT.EDITOR,
          eventType: EVENT_TYPE.OPERATIONAL,
          attributes: {
            transformedNodeTypes: transformedNodeTypes
          }
        });
      }
      return {
        transformedAdf: transformedAdf,
        isTransformed: isTransformed
      };
    }
  } catch (e) {
    // eslint-disable-next-line no-console
    console.error('Failed to transform one or more panels to panel_c1');
    if (dispatchAnalyticsEvent) {
      dispatchAnalyticsEvent({
        action: ACTION.DOCUMENT_PROCESSING_ERROR,
        actionSubject: ACTION_SUBJECT.EDITOR,
        eventType: EVENT_TYPE.OPERATIONAL,
        attributes: {
          errorMessage: "".concat(e instanceof Error && e.name === 'NodeNestingTransformError' ? 'NodeNestingTransformError - Failed to transform panel to panel_c1' : undefined)
        }
      });
    }
  }
  return {
    transformedAdf: node,
    isTransformed: false
  };
};
export function processRawValueWithoutValidation(schema, value, dispatchAnalyticsEvent) {
  if (!value) {
    return;
  }
  var node;
  if (typeof value === 'string') {
    try {
      node = JSON.parse(value);
    } catch (_unused) {
      // eslint-disable-next-line no-console
      console.error("Error processing value: ".concat(value, " isn't a valid JSON"));
      return;
    }
  } else {
    node = value;
  }

  // Convert nested-table extensions into nested tables
  var _transformNestedTable2 = transformNestedTablesWithAnalytics(node, dispatchAnalyticsEvent),
    transformedAdf = _transformNestedTable2.transformedAdf;
  var result = syncBlockFallbackTransform(schema, transformedAdf);
  if (result.isTransformed && result.transformedAdf) {
    transformedAdf = result.transformedAdf;
  }
  if (expValEquals('platform_editor_nest_table_in_panel', 'isEnabled', true)) {
    var _transformContainerNo2 = transformContainerNodesWithAnalytics(transformedAdf, schema, dispatchAnalyticsEvent);
    transformedAdf = _transformContainerNo2.transformedAdf;
  }
  return Node.fromJSON(schema, transformedAdf);
}

// eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
export function processRawValue(schema, value, providerFactory, sanitizePrivateContent, contentTransformer, dispatchAnalyticsEvent) {
  if (!value) {
    return;
  }
  var node;
  if (typeof value === 'string') {
    try {
      if (contentTransformer) {
        var doc = contentTransformer.parse(value);
        node = doc.toJSON();
      } else {
        node = JSON.parse(value);
      }
    } catch (_unused2) {
      // eslint-disable-next-line no-console
      console.error("Error processing value: ".concat(value, " isn't a valid JSON"));
      return;
    }
  } else {
    node = value;
  }
  if (Array.isArray(node)) {
    // eslint-disable-next-line no-console
    console.error("Error processing value: ".concat(node, " is an array, but it must be an object."));
    return;
  }
  try {
    // ProseMirror always require a child under doc
    if (node.type === 'doc') {
      if (Array.isArray(node.content) && node.content.length === 0) {
        node.content.push({
          type: 'paragraph',
          content: []
        });
      }
      // Just making sure doc is always valid
      if (!node.version) {
        node.version = 1;
      }
    }
    if (contentTransformer) {
      return Node.fromJSON(schema, node);
    }

    // link mark on mediaSingle is deprecated, need to move link mark to child media node
    // https://product-fabric.atlassian.net/browse/ED-14043
    var _transformMediaLinkMa = transformMediaLinkMarks(node),
      transformedAdf = _transformMediaLinkMa.transformedAdf,
      isTransformed = _transformMediaLinkMa.isTransformed;
    if (isTransformed && dispatchAnalyticsEvent) {
      dispatchAnalyticsEvent({
        action: ACTION.MEDIA_LINK_TRANSFORMED,
        actionSubject: ACTION_SUBJECT.EDITOR,
        eventType: EVENT_TYPE.OPERATIONAL
      });
    }

    // Fix mediaSingle width issues
    var _transformMediaSingle = transformMediaSingleWidth(transformedAdf);
    transformedAdf = _transformMediaSingle.transformedAdf;
    isTransformed = _transformMediaSingle.isTransformed;
    if (isTransformed && dispatchAnalyticsEvent) {
      dispatchAnalyticsEvent({
        action: ACTION.MEDIA_SINGLE_WIDTH_TRANSFORMED,
        actionSubject: ACTION_SUBJECT.EDITOR,
        eventType: EVENT_TYPE.OPERATIONAL
      });
    }

    // See: HOT-97965 https://product-fabric.atlassian.net/browse/ED-14400
    // We declared in code mark spec that links and marks should not co-exist on
    // text nodes. This util strips code marks from bad text nodes and preserves links.
    // Otherwise, prosemirror will try to repair the invalid document by stripping links
    // and preserving code marks during content changes.
    var _transformTextLinkCod = transformTextLinkCodeMarks(transformedAdf);
    transformedAdf = _transformTextLinkCod.transformedAdf;
    isTransformed = _transformTextLinkCod.isTransformed;
    if (isTransformed && dispatchAnalyticsEvent) {
      dispatchAnalyticsEvent({
        action: ACTION.TEXT_LINK_MARK_TRANSFORMED,
        actionSubject: ACTION_SUBJECT.EDITOR,
        eventType: EVENT_TYPE.OPERATIONAL
      });
    }
    var discardedMarks = [];
    var _transformDedupeMarks = transformDedupeMarks(transformedAdf);
    transformedAdf = _transformDedupeMarks.transformedAdf;
    isTransformed = _transformDedupeMarks.isTransformed;
    discardedMarks = _transformDedupeMarks.discardedMarks;
    if (isTransformed && dispatchAnalyticsEvent) {
      dispatchAnalyticsEvent({
        action: ACTION.DEDUPE_MARKS_TRANSFORMED_V2,
        actionSubject: ACTION_SUBJECT.EDITOR,
        eventType: EVENT_TYPE.OPERATIONAL,
        attributes: {
          /** UGC WARNING
           *
           * DO NOT include the `mark` attributes inside, we map here to only
           * extract the mark type as that is the only non-UGC safe information
           * that we can add to event-attributes
           *
           */
          discardedMarkTypes: discardedMarks.map(function (mark) {
            return mark.type;
          })
        }
      });
    }
    var _transformNodesMissin = transformNodesMissingContent(transformedAdf);
    transformedAdf = _transformNodesMissin.transformedAdf;
    isTransformed = _transformNodesMissin.isTransformed;
    if (isTransformed && dispatchAnalyticsEvent) {
      dispatchAnalyticsEvent({
        action: ACTION.NODES_MISSING_CONTENT_TRANSFORMED,
        actionSubject: ACTION_SUBJECT.EDITOR,
        eventType: EVENT_TYPE.OPERATIONAL
      });
    }
    var _transformIndentation = transformIndentationMarks(transformedAdf);
    transformedAdf = _transformIndentation.transformedAdf;
    isTransformed = _transformIndentation.isTransformed;
    if (isTransformed && dispatchAnalyticsEvent) {
      dispatchAnalyticsEvent({
        action: ACTION.INDENTATION_MARKS_TRANSFORMED,
        actionSubject: ACTION_SUBJECT.EDITOR,
        eventType: EVENT_TYPE.OPERATIONAL
      });
    }
    var _transformInvalidMedi = transformInvalidMediaContent(transformedAdf);
    transformedAdf = _transformInvalidMedi.transformedAdf;
    isTransformed = _transformInvalidMedi.isTransformed;
    if (isTransformed && dispatchAnalyticsEvent) {
      dispatchAnalyticsEvent({
        action: ACTION.INVALID_MEDIA_CONTENT_TRANSFORMED,
        actionSubject: ACTION_SUBJECT.EDITOR,
        eventType: EVENT_TYPE.OPERATIONAL
      });
    }
    if (dispatchAnalyticsEvent) {
      var _transformedAdf$conte;
      var hasSingleColumnLayout = (_transformedAdf$conte = transformedAdf.content) === null || _transformedAdf$conte === void 0 ? void 0 : _transformedAdf$conte.some(function (node) {
        var _node$content;
        return node && node.type === 'layoutSection' && ((_node$content = node.content) === null || _node$content === void 0 ? void 0 : _node$content.length) === 1;
      });
      if (hasSingleColumnLayout) {
        dispatchAnalyticsEvent({
          action: ACTION.SINGLE_COL_LAYOUT_DETECTED,
          actionSubject: ACTION_SUBJECT.EDITOR,
          eventType: EVENT_TYPE.OPERATIONAL
        });
      }
    }

    // Validate ADF first before converting nested-table extensions into nested tables
    // This matches the renderer's behavior in render-document.ts
    var allowNestedTables = isNestedTablesSupported(schema);
    var allowTableInPanel = isPanelNestingTableSupported(schema);
    var validateADFEntityOptions = allowNestedTables || allowTableInPanel ? {
      allowNestedTables: allowNestedTables || undefined,
      allowTableInPanel: allowTableInPanel || undefined
    } : undefined;
    var entity = validateADFEntity(schema, transformedAdf || node, dispatchAnalyticsEvent, validateADFEntityOptions);

    // Convert nested-table extensions into nested tables
    var _transformNestedTable3 = transformNestedTablesWithAnalytics(entity, dispatchAnalyticsEvent);
    transformedAdf = _transformNestedTable3.transformedAdf;
    entity = transformedAdf;
    if (expValEquals('platform_editor_nest_table_in_panel', 'isEnabled', true)) {
      var _transformContainerNo3 = transformContainerNodesWithAnalytics(entity, schema, dispatchAnalyticsEvent);
      transformedAdf = _transformContainerNo3.transformedAdf;
      entity = transformedAdf;
    }
    var newEntity = maySanitizePrivateContent(entity, providerFactory, sanitizePrivateContent);
    var parsedDoc = Node.fromJSON(schema, newEntity);

    // throws an error if the document is invalid
    try {
      parsedDoc.check();
    } catch (err) {
      if (dispatchAnalyticsEvent) {
        dispatchAnalyticsEvent({
          action: ACTION.INVALID_PROSEMIRROR_DOCUMENT,
          actionSubject: ACTION_SUBJECT.EDITOR,
          eventType: EVENT_TYPE.OPERATIONAL
        });
      }
      throw err;
    }
    if (dispatchAnalyticsEvent) {
      findAndTrackUnsupportedContentNodes(parsedDoc, schema, dispatchAnalyticsEvent);
    }
    return parsedDoc;
  } catch (e) {
    if (dispatchAnalyticsEvent) {
      dispatchAnalyticsEvent({
        action: ACTION.DOCUMENT_PROCESSING_ERROR,
        actionSubject: ACTION_SUBJECT.EDITOR,
        eventType: EVENT_TYPE.OPERATIONAL
      });
    }

    // eslint-disable-next-line no-console
    console.error("Error processing document:\n".concat(e instanceof Error ? e.message : String(e), "\n\n"), JSON.stringify(node));
    if (isProseMirrorSchemaCheckError(e)) {
      throw e;
    }
    return;
  }
}

// Ignored via go/ees005
// eslint-disable-next-line require-unicode-regexp
var INVALID_MARKS_REGEX = /^Invalid collection of marks for node/;
// Ignored via go/ees005
// eslint-disable-next-line require-unicode-regexp
var INVALID_CONTENT_REGEX = /^Invalid content for node/;
function isProseMirrorSchemaCheckError(error) {
  return error instanceof RangeError && (!!error.message.match(INVALID_MARKS_REGEX) || !!error.message.match(INVALID_CONTENT_REGEX));
}
var maySanitizePrivateContent = function maySanitizePrivateContent(entity, providerFactory, sanitizePrivateContent) {
  if (sanitizePrivateContent && providerFactory) {
    return sanitizeNodeForPrivacy(entity, providerFactory);
  }
  return entity;
};
// eslint-disable-next-line @atlaskit/editor/no-re-export
export { processRawFragmentValue } from './processRawFragmentValue';