"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.applyMarkOnRange = void 0;
Object.defineProperty(exports, "entireSelectionContainsMark", {
  enumerable: true,
  get: function get() {
    return _entireSelectionContainsMark.entireSelectionContainsMark;
  }
});
Object.defineProperty(exports, "filterChildrenBetween", {
  enumerable: true,
  get: function get() {
    return _filterChildrenBetween.filterChildrenBetween;
  }
});
Object.defineProperty(exports, "removeMark", {
  enumerable: true,
  get: function get() {
    return _removeMark2.removeMark;
  }
});
exports.toggleMark = void 0;
exports.transformNonTextNodesToText = transformNonTextNodesToText;
var _state = require("@atlaskit/editor-prosemirror/state");
var _cellSelection = require("@atlaskit/editor-tables/cell-selection");
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
var _entireSelectionContainsMark = require("./entireSelectionContainsMark");
var _filterChildrenBetween = require("./filterChildrenBetween");
var _removeMark2 = require("./removeMark");
// eslint-disable-next-line no-duplicate-imports

var SMART_TO_ASCII = {
  '…': '...',
  '→': '->',
  '←': '<-',
  '–': '--',
  '“': '"',
  '”': '"',
  '‘': "'",
  '’': "'"
};

// Ignored via go/ees005
// eslint-disable-next-line require-unicode-regexp
var FIND_SMART_CHAR = new RegExp("[".concat(Object.keys(SMART_TO_ASCII).join(''), "]"), 'g');
function transformNonTextNodesToText(from, to, tr) {
  var doc = tr.doc;
  var schema = doc.type.schema;
  var _schema$nodes = schema.nodes,
    mentionNodeType = _schema$nodes.mention,
    textNodeType = _schema$nodes.text,
    emojiNodeType = _schema$nodes.emoji,
    inlineCardNodeType = _schema$nodes.inlineCard;
  var nodesToChange = [];
  doc.nodesBetween(from, to, function (node, pos, _parent) {
    if ([mentionNodeType, textNodeType, emojiNodeType, inlineCardNodeType].includes(node.type)) {
      nodesToChange.push({
        node: node,
        pos: pos
      });
    }
  });
  nodesToChange.forEach(function (_ref) {
    var node = _ref.node,
      pos = _ref.pos;
    if (node.type !== textNodeType) {
      var newText = node.attrs.url ||
      // url for inlineCard
      node.attrs.text || "".concat(node.type.name, " text missing"); // fallback for missing text

      var currentPos = tr.mapping.map(pos);
      tr.replaceWith(currentPos, currentPos + node.nodeSize, schema.text(newText, node.marks));
    } else if (node.text) {
      // Find a valid start and end position because the text may be partially selected.
      var startPositionInSelection = Math.max(pos, from);
      var endPositionInSelection = Math.min(pos + node.nodeSize, to);
      var textForReplacing = doc.textBetween(startPositionInSelection, endPositionInSelection);

      // eslint-disable-next-line @atlassian/perf-linting/no-expensive-split-replace -- Ignored via go/ees017 (to be fixed)
      var _newText = textForReplacing.replace(FIND_SMART_CHAR, function (match) {
        var _SMART_TO_ASCII$match;
        return (_SMART_TO_ASCII$match = SMART_TO_ASCII[match]) !== null && _SMART_TO_ASCII$match !== void 0 ? _SMART_TO_ASCII$match : match;
      });
      var currentStartPos = tr.mapping.map(startPositionInSelection);
      var currentEndPos = tr.mapping.map(endPositionInSelection);
      tr.replaceWith(currentStartPos, currentEndPos, schema.text(_newText, node.marks));
    }
  });
}

// eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
var applyMarkOnRange = exports.applyMarkOnRange = function applyMarkOnRange(from, to, removeMark, mark, tr) {
  var schema = tr.doc.type.schema;
  var code = schema.marks.code;
  if (mark.type === code) {
    transformNonTextNodesToText(from, to, tr);
  }
  tr.doc.nodesBetween(tr.mapping.map(from), tr.mapping.map(to), function (node, pos) {
    if ((0, _platformFeatureFlags.fg)('editor_inline_comments_on_inline_nodes')) {
      if (!node.isText) {
        var isAllowedInlineNode = ['emoji', 'status', 'date', 'mention', 'inlineCard'].includes(node.type.name);
        if (!isAllowedInlineNode) {
          return true;
        }
      }
    } else {
      if (!node.isText) {
        return true;
      }
    }

    // This is an issue when the user selects some text.
    // We need to check if the current node position is less than the range selection from.
    // If it’s true, that means we should apply the mark using the range selection,
    // not the current node position.
    var nodeBetweenFrom = Math.max(pos, tr.mapping.map(from));
    var nodeBetweenTo = Math.min(pos + node.nodeSize, tr.mapping.map(to));
    if (removeMark) {
      tr.removeMark(nodeBetweenFrom, nodeBetweenTo, mark);
    } else {
      tr.addMark(nodeBetweenFrom, nodeBetweenTo, mark);
    }
    return true;
  });
  return tr;
};
var toggleMarkInRange = function toggleMarkInRange(mark) {
  return function (_ref2) {
    var tr = _ref2.tr;
    if (tr.selection instanceof _cellSelection.CellSelection) {
      var removeMark = true;
      var cells = [];
      tr.selection.forEachCell(function (cell, cellPos) {
        cells.push({
          node: cell,
          pos: cellPos
        });
        var from = cellPos;
        var to = cellPos + cell.nodeSize;
        removeMark && (removeMark = (0, _entireSelectionContainsMark.entireSelectionContainsMark)(mark, tr.doc, from, to));
      });
      for (var i = cells.length - 1; i >= 0; i--) {
        var cell = cells[i];
        var from = cell.pos;
        var to = from + cell.node.nodeSize;
        applyMarkOnRange(from, to, removeMark, mark, tr);
      }
    } else {
      var _tr$selection = tr.selection,
        $from = _tr$selection.$from,
        $to = _tr$selection.$to;
      // We decide to remove the mark only if the entire selection contains the mark
      // Examples with *bold* text
      // Scenario 1: Selection contains both bold and non-bold text -> bold entire selection
      // Scenario 2: Selection contains only bold text -> un-bold entire selection
      // Scenario 3: Selection contains no bold text -> bold entire selection
      var _removeMark = (0, _entireSelectionContainsMark.entireSelectionContainsMark)(mark, tr.doc, $from.pos, $to.pos);
      applyMarkOnRange($from.pos, $to.pos, _removeMark, mark, tr);
    }
    if (tr.docChanged) {
      return tr;
    }
    return null;
  };
};

/**
 * A custom version of the ProseMirror toggleMark, where we only toggle marks
 * on text nodes in the selection rather than all inline nodes.
 * @param markType
 * @param attrs
 */
// eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
var toggleMark = exports.toggleMark = function toggleMark(markType, attrs) {
  return function (_ref3) {
    var tr = _ref3.tr;
    var mark = markType.create(attrs);

    // For cursor selections we can use the default behaviour.
    if (tr.selection instanceof _state.TextSelection && tr.selection.$cursor) {
      if (mark.isInSet(tr.storedMarks || tr.selection.$cursor.marks())) {
        tr.removeStoredMark(mark);
      } else {
        tr.addStoredMark(mark);
      }
      return tr;
    }
    return toggleMarkInRange(mark)({
      tr: tr
    });
  };
};
// eslint-disable-next-line @atlaskit/editor/no-re-export

// eslint-disable-next-line @atlaskit/editor/no-re-export

// eslint-disable-next-line @atlaskit/editor/no-re-export