"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.bracketTyped = bracketTyped;
exports.findFarthestParentNode = void 0;
exports.getNodesCount = getNodesCount;
exports.getStepRange = void 0;
exports.hasDocAsParent = hasDocAsParent;
exports.hasVisibleContent = hasVisibleContent;
exports.isEmptyDocument = isEmptyDocument;
exports.isEmptyParagraph = isEmptyParagraph;
exports.isInEmptyLine = isInEmptyLine;
exports.isNodeEmpty = isNodeEmpty;
exports.isSelectionEndOfParagraph = void 0;
exports.nodesBetweenChanged = nodesBetweenChanged;

/**
 * Checks if node is an empty paragraph.
 */
function isEmptyParagraph(node) {
  return !node || node.type.name === 'paragraph' && !node.textContent && !node.childCount;
}
/**
 * Returns false if node contains only empty inline nodes and hardBreaks.
 */


function hasVisibleContent(node) {
  var isInlineNodeHasVisibleContent = function isInlineNodeHasVisibleContent(inlineNode) {
    return inlineNode.isText ? !!inlineNode.textContent.trim() : inlineNode.type.name !== 'hardBreak';
  };

  if (node.isInline) {
    return isInlineNodeHasVisibleContent(node);
  } else if (node.isBlock && (node.isLeaf || node.isAtom)) {
    return true;
  } else if (!node.childCount) {
    return false;
  }

  for (var _index = 0; _index < node.childCount; _index++) {
    var child = node.child(_index);

    if (hasVisibleContent(child)) {
      return true;
    }
  }

  return false;
}
/**
 * Checks if a node has any content. Ignores node that only contain empty block nodes.
 */


function isNodeEmpty(node) {
  if (node && node.textContent) {
    return false;
  }

  if (!node || !node.childCount || node.childCount === 1 && isEmptyParagraph(node.firstChild)) {
    return true;
  }

  var block = [];
  var nonBlock = [];
  node.forEach(function (child) {
    child.isInline ? nonBlock.push(child) : block.push(child);
  });
  return !nonBlock.length && !block.filter(function (childNode) {
    return !!childNode.childCount && !(childNode.childCount === 1 && isEmptyParagraph(childNode.firstChild)) || childNode.isAtom;
  }).length;
}
/**
 * Checks if a node looks like an empty document
 */


function isEmptyDocument(node) {
  var nodeChild = node.content.firstChild;

  if (node.childCount !== 1 || !nodeChild) {
    return false;
  }

  return nodeChild.type.name === 'paragraph' && !nodeChild.childCount && nodeChild.nodeSize === 2 && (!nodeChild.marks || nodeChild.marks.length === 0);
}

var getStepRange = function getStepRange(transaction) {
  var from = -1;
  var to = -1;
  transaction.steps.forEach(function (step) {
    step.getMap().forEach(function (_oldStart, _oldEnd, newStart, newEnd) {
      from = newStart < from || from === -1 ? newStart : from;
      to = newEnd < to || to === -1 ? newEnd : to;
    });
  });

  if (from !== -1) {
    return {
      from: from,
      to: to
    };
  }

  return null;
};
/**
 * Find the farthest node given a condition
 * @param predicate Function to check the node
 */


exports.getStepRange = getStepRange;

var findFarthestParentNode = function findFarthestParentNode(predicate) {
  return function ($pos) {
    var candidate = null;

    for (var i = $pos.depth; i > 0; i--) {
      var _node = $pos.node(i);

      if (predicate(_node)) {
        candidate = {
          pos: i > 0 ? $pos.before(i) : 0,
          start: $pos.start(i),
          depth: i,
          node: _node
        };
      }
    }

    return candidate;
  };
};

exports.findFarthestParentNode = findFarthestParentNode;

var isSelectionEndOfParagraph = function isSelectionEndOfParagraph(state) {
  return state.selection.$to.parent.type === state.schema.nodes.paragraph && state.selection.$to.pos === state.doc.resolve(state.selection.$to.pos).end();
};

exports.isSelectionEndOfParagraph = isSelectionEndOfParagraph;

function nodesBetweenChanged(tr, f, startPos) {
  var stepRange = getStepRange(tr);

  if (!stepRange) {
    return;
  }

  tr.doc.nodesBetween(stepRange.from, stepRange.to, f, startPos);
}

function getNodesCount(node) {
  var count = {};
  node.nodesBetween(0, node.nodeSize - 2, function (node) {
    count[node.type.name] = (count[node.type.name] || 0) + 1;
  });
  return count;
} // Checks to see if the parent node is the document, ie not contained within another entity


function hasDocAsParent($anchor) {
  return $anchor.depth === 1;
}

function isInEmptyLine(state) {
  var selection = state.selection;
  var _ref = selection,
      $cursor = _ref.$cursor,
      $anchor = _ref.$anchor;

  if (!$cursor) {
    return false;
  }

  var node = $cursor.node();

  if (!node) {
    return false;
  }

  return isEmptyParagraph(node) && hasDocAsParent($anchor);
}

function bracketTyped(state) {
  var selection = state.selection;
  var _ref2 = selection,
      $cursor = _ref2.$cursor,
      $anchor = _ref2.$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;
}