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; }
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; }
import { ReplaceStep } from '@atlaskit/editor-prosemirror/transform';
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
import { getStepRange } from './getStepRange';
import { hasDocAsParent } from './hasDocAsParent';
export function bracketTyped(state) {
  var selection = state.selection;
  var _ref = selection,
    $cursor = _ref.$cursor,
    $anchor = _ref.$anchor;
  if (!$cursor) {
    return false;
  }
  var node = $cursor.nodeBefore;
  if (!node) {
    return false;
  }
  if (node.type.name === 'text' && node.text === '{') {
    var paragraphNode = $anchor.node();
    return paragraphNode.marks.length === 0 && hasDocAsParent($anchor);
  }
  return false;
}

// eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
export function nodesBetweenChanged(tr, f, startPos) {
  var stepRange = getStepRange(tr);
  if (!stepRange) {
    return;
  }
  tr.doc.nodesBetween(stepRange.from, stepRange.to, f, startPos);
}
function getChangedNodesIn(_ref2) {
  var tr = _ref2.tr,
    doc = _ref2.doc;
  var nodes = [];
  var stepRange = getStepRange(tr);
  if (!stepRange) {
    return nodes;
  }
  var from = Math.min(doc.nodeSize - 2, stepRange.from);
  var to = Math.min(doc.nodeSize - 2, stepRange.to);
  doc.nodesBetween(from, to, function (node, pos) {
    nodes.push({
      node: node,
      pos: pos
    });
  });
  return nodes;
}

// eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
export function getChangedNodes(tr) {
  return getChangedNodesIn({
    tr: tr,
    doc: tr.doc
  });
}
// When document first load in Confluence, initially it is an empty document
// and Collab service triggers a transaction to replace the empty document with the real document that should be rendered.
// isReplaceDocumentOperation is checking if the transaction is the one that replace the empty document with the real document
// eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
export var isReplaceDocOperation = function isReplaceDocOperation(transactions, oldState) {
  return transactions.some(function (tr) {
    if (tr.getMeta('replaceDocument')) {
      return true;
    }
    var hasStepReplacingEntireDocument = tr.steps.some(function (step) {
      if (!(step instanceof ReplaceStep)) {
        return false;
      }
      var isStepReplacingFromDocStart = step.from === 0;
      var isStepReplacingUntilTheEndOfDocument = step.to === oldState.doc.content.size;
      if (!isStepReplacingFromDocStart || !isStepReplacingUntilTheEndOfDocument) {
        return false;
      }
      return true;
    });
    return hasStepReplacingEntireDocument;
  });
};
function marksEqualInOrder(m1, m2) {
  if (m1.length !== m2.length) return false;
  return m1.every(function (m, i) {
    return m.eq(m2[i]);
  });
}
function marksEqualIgnoringOrder(m1, m2) {
  if (m1.length !== m2.length) {
    return false;
  }
  var m2Used = new Set();
  var _iterator = _createForOfIteratorHelper(m1),
    _step;
  try {
    var _loop = function _loop() {
        var mark1 = _step.value;
        var idx = m2.findIndex(function (mark2, i) {
          return !m2Used.has(i) && mark1.eq(mark2);
        });
        if (idx === -1) {
          return {
            v: false
          };
        }
        m2Used.add(idx);
      },
      _ret;
    for (_iterator.s(); !(_step = _iterator.n()).done;) {
      _ret = _loop();
      if (_ret) return _ret.v;
    }
  } catch (err) {
    _iterator.e(err);
  } finally {
    _iterator.f();
  }
  return true;
}
/**
 * Compares two ProseMirror documents for equality, ignoring attributes
 * which don't affect the document structure.
 *
 * This is almost a copy of the .eq() PM function - tweaked to ignore attrs
 *
 * @param doc1 PMNode
 * @param doc2 PMNode
 * @param attributesToIgnore Specific array of attribute keys to ignore - defaults to ignoring all
 * @param opts.ignoreMarkOrder If mark order should be ignored to still be equal (e.g. reversed annotation marks). Defaults to true.
 * @returns boolean
 */

// eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
export function areNodesEqualIgnoreAttrs(node1, node2, attributesToIgnore, opts) {
  var _opts$ignoreMarkOrder;
  var ignoreMarkOrder = (_opts$ignoreMarkOrder = opts === null || opts === void 0 ? void 0 : opts.ignoreMarkOrder) !== null && _opts$ignoreMarkOrder !== void 0 ? _opts$ignoreMarkOrder : true;
  if (node1.isText) {
    if (ignoreMarkOrder) {
      return node1.text === node2.text && marksEqualIgnoringOrder(node1.marks, node2.marks);
    }
    return node1.eq(node2);
  }
  var marksEqual = ignoreMarkOrder ? marksEqualIgnoringOrder(node1.marks, node2.marks) : marksEqualInOrder(node1.marks, node2.marks);

  // If no attributes to ignore, compare all attributes
  if (!attributesToIgnore || attributesToIgnore.length === 0) {
    return node1 === node2 || node1.hasMarkup(node2.type, node1.attrs, node1.marks) && marksEqual && areFragmentsEqual(node1.content, node2.content, undefined, opts);
  }

  // Build attrs to compare by excluding ignored attributes
  var attrsToCompare = expValEquals('platform_editor_show_diff_fix_missing_attrs', 'isEnabled', true) ? _objectSpread({}, node2.attrs) : node2.attrs;
  var ignoreSet = new Set(attributesToIgnore);
  for (var key in node2.attrs) {
    if (ignoreSet.has(key)) {
      attrsToCompare[key] = node1.attrs[key];
    }
  }
  return node1 === node2 || node1.type === node2.type && node1.hasMarkup(node2.type, attrsToCompare, node1.marks) && marksEqual && areFragmentsEqual(node1.content, node2.content, attributesToIgnore, opts);
}
function areFragmentsEqual(frag1, frag2, attributesToIgnore, opts) {
  if (frag1.content.length !== frag2.content.length) {
    return false;
  }
  var childrenEqual = true;
  frag1.content.forEach(function (child, i) {
    var otherChild = frag2.child(i);
    if (child === otherChild || otherChild && areNodesEqualIgnoreAttrs(child, otherChild, attributesToIgnore, opts)) {
      return;
    }
    childrenEqual = false;
  });
  return childrenEqual;
}
// eslint-disable-next-line @atlaskit/editor/no-re-export
export { getStepRange } from './getStepRange';
// eslint-disable-next-line @atlaskit/editor/no-re-export
export { hasDocAsParent } from './hasDocAsParent';
// eslint-disable-next-line @atlaskit/editor/no-re-export
export { isEmptyDocument } from './isEmptyDocument';
// eslint-disable-next-line @atlaskit/editor/no-re-export
export { hasVisibleContent } from './hasVisibleContent';
// eslint-disable-next-line @atlaskit/editor/no-re-export
export { isSelectionEndOfParagraph } from './isSelectionEndOfParagraph';