"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.parseHTMLTextContent = void 0;
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _schemaDefault = require("@atlaskit/adf-schema/schema-default");
var _model = require("@atlaskit/editor-prosemirror/model");
var _getNestingRulesFromSchema = require("./getNestingRulesFromSchema");
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) { (0, _defineProperty2.default)(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; }
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
var domParser = _model.DOMParser.fromSchema(_schemaDefault.defaultSchema);
var NESTING_RULES = (0, _getNestingRulesFromSchema.getNestingRulesFromSchema)();
var canContainChildren = function canContainChildren(nodeType) {
  var _NESTING_RULES$nodeTy;
  return !!((_NESTING_RULES$nodeTy = NESTING_RULES[nodeType]) !== null && _NESTING_RULES$nodeTy !== void 0 && _NESTING_RULES$nodeTy.length);
};
var isAllowedChild = function isAllowedChild(parent, child) {
  var _NESTING_RULES$parent, _NESTING_RULES$parent2;
  return (_NESTING_RULES$parent = (_NESTING_RULES$parent2 = NESTING_RULES[parent]) === null || _NESTING_RULES$parent2 === void 0 ? void 0 : _NESTING_RULES$parent2.includes(child)) !== null && _NESTING_RULES$parent !== void 0 ? _NESTING_RULES$parent : false;
};
var shouldApplyMark = function shouldApplyMark(tag) {
  return domParser.rules.some(function (rule) {
    return 'mark' in rule && rule.tag === tag;
  });
};
var isBlockElement = function isBlockElement(tag) {
  return domParser.rules.some(function (rule) {
    return rule.tag === tag && rule.node;
  });
};
var getMarkTypes = function getMarkTypes(tags) {
  var seen = new Set();
  var marks = [];
  var _iterator = _createForOfIteratorHelper(tags),
    _step;
  try {
    var _loop = function _loop() {
      var _domParser$rules$find;
      var tag = _step.value;
      var markType = (_domParser$rules$find = domParser.rules.find(function (rule) {
        return rule.tag === tag;
      })) === null || _domParser$rules$find === void 0 ? void 0 : _domParser$rules$find.mark;
      if (markType && !seen.has(markType)) {
        marks.push({
          type: markType
        });
        seen.add(markType);
      }
    };
    for (_iterator.s(); !(_step = _iterator.n()).done;) {
      _loop();
    }
  } catch (err) {
    _iterator.e(err);
  } finally {
    _iterator.f();
  }
  return marks;
};
var createParagraph = function createParagraph() {
  var content = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
  return {
    type: 'paragraph',
    content: content
  };
};
var getBlockType = function getBlockType(tag) {
  var rule = domParser.rules.find(function (r) {
    return r.tag === tag;
  });
  return rule && 'node' in rule && rule.node ? rule.node : 'paragraph';
};
var createTextNode = function createTextNode(text, marks) {
  var markTypes = getMarkTypes(marks);
  return _objectSpread({
    type: 'text',
    text: text
  }, markTypes.length > 0 && {
    marks: markTypes
  });
};
var addText = function addText(text, marks, content) {
  if (text) {
    content.push(createTextNode(text, marks));
  }
};
var handleBlockElement = function handleBlockElement(tag, innerContent, marks, blocks, currentParagraphContent, parseNode, nestedContainer) {
  // Push any accumulated content as paragraph before block element
  if (currentParagraphContent.length > 0) {
    blocks.push(createParagraph((0, _toConsumableArray2.default)(currentParagraphContent)));
    currentParagraphContent.length = 0;
  }
  var blockType = getBlockType(tag);
  var newMarks = shouldApplyMark(tag) ? [].concat((0, _toConsumableArray2.default)(marks), [tag]) : marks;
  var parentNodeType = nestedContainer === null || nestedContainer === void 0 ? void 0 : nestedContainer.parentType;
  if (nestedContainer && parentNodeType && isAllowedChild(parentNodeType, blockType)) {
    var elementContent = [];
    var childNestedContainer = canContainChildren(blockType) ? {
      parentType: blockType,
      children: elementContent
    } : nestedContainer;
    parseNode(innerContent, newMarks, childNestedContainer);
    if (currentParagraphContent.length > 0) {
      elementContent.push(createParagraph((0, _toConsumableArray2.default)(currentParagraphContent)));
      currentParagraphContent.length = 0;
    }
    nestedContainer.children.push({
      type: blockType,
      content: elementContent.length > 0 ? elementContent : [createParagraph()]
    });
  } else if (canContainChildren(blockType)) {
    var children = [];
    parseNode(innerContent, newMarks, {
      parentType: blockType,
      children: children
    });
    blocks.push({
      type: blockType,
      content: children.length > 0 ? children : [createParagraph()]
    });
  } else {
    // Regular block elements
    parseNode(innerContent, newMarks, nestedContainer);

    // Push content generated from block parsing
    if (currentParagraphContent.length > 0) {
      if (blockType === 'paragraph' || blockType === 'codeBlock') {
        blocks.push({
          type: blockType,
          content: (0, _toConsumableArray2.default)(currentParagraphContent)
        });
      }
      currentParagraphContent.length = 0;
    }
  }
};
var handleInlineElement = function handleInlineElement(tag, innerContent, marks, parseNode, nestedContainer) {
  var newMarks = shouldApplyMark(tag) ? [].concat((0, _toConsumableArray2.default)(marks), [tag]) : marks;
  parseNode(innerContent, newMarks, nestedContainer);
};

/**
 * Simple SSR-compatible parser that recognises text wrapped in HTML elements
 * and extracts their content as ADF.
 *
 * Designed specifically for parsing i18n strings for ADF which specifically need to be
 * HTML strings for translation.
 *
 * Supports nested structures automatically derived from the ADF schema:
 * - Lists: ul/ol → li (listItem)
 * - Tables: table → tr (tableRow) → td/th (tableCell/tableHeader)
 * - Paragraphs, code blocks, and text marks
 * - Any other nested structures defined in the schema
 *
 * @param html - The HTML string to parse
 * @returns ADF DocNode containing the parsed content
 */
var parseHTMLTextContent = exports.parseHTMLTextContent = function parseHTMLTextContent(html) {
  var blocks = [];
  var currentParagraphContent = [];

  // Simple regex-based parser that works in both SSR and browser
  var _parseNode = function parseNode(content) {
    var marks = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
    var nestedContainer = arguments.length > 2 ? arguments[2] : undefined;
    // Match HTML tags and text content
    // eslint-disable-next-line require-unicode-regexp
    var tagRegex = /<\s*(\w+)([^>]*)>([\s\S]*?)<\s*\/\s*\1\s*>|([^<]+)/g;
    var match = tagRegex.exec(content);
    while (match !== null) {
      if (match[4]) {
        addText(match[4], marks, currentParagraphContent);
      } else {
        // HTML element
        var tag = match[1].toLowerCase();
        var innerContent = match[3];
        if (isBlockElement(tag)) {
          handleBlockElement(tag, innerContent, marks, blocks, currentParagraphContent, _parseNode, nestedContainer);
        } else {
          handleInlineElement(tag, innerContent, marks, _parseNode, nestedContainer);
        }
      }
      match = tagRegex.exec(content);
    }
  };
  _parseNode(html);

  // Push any remaining content
  if (currentParagraphContent.length > 0) {
    blocks.push(createParagraph(currentParagraphContent));
  }
  return {
    type: 'doc',
    version: 1,
    content: blocks.length > 0 ? blocks : [createParagraph()]
  };
};
// eslint-disable-next-line @atlaskit/editor/no-re-export