"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.convertListType = convertListType;

var _prosemirrorState = require("prosemirror-state");

var _prosemirrorModel = require("prosemirror-model");

var _prosemirrorTransform = require("prosemirror-transform");

var _prosemirrorUtils = require("prosemirror-utils");

var _node = require("../utils/node");

var _find = require("../utils/find");

// import { isEmptyParagraph } from '../../../utils';
function isEmptyParagraph(node) {
  return !!node && node.type.name === 'paragraph' && !node.childCount;
}

function convertListType(_ref) {
  var tr = _ref.tr,
      nextListNodeType = _ref.nextListNodeType;
  var doc = tr.doc,
      _tr$selection = tr.selection,
      $from = _tr$selection.$from,
      $to = _tr$selection.$to;
  var listRange = $from.blockRange($to, _node.isListNode);

  if (listRange) {
    return convertSelectedList({
      tr: tr,
      nextListNodeType: nextListNodeType
    });
  }

  var nodeRangeAroundList = $from.blockRange($to);

  if (!nodeRangeAroundList) {
    return;
  }

  var parentNode = nodeRangeAroundList.parent;
  var startIndex = nodeRangeAroundList.startIndex,
      endIndex = nodeRangeAroundList.endIndex,
      depth = nodeRangeAroundList.depth; // Checking for invalid nodes to prevent conversion
  // eg. a panel cannot be wrapped in a list so return
  // It will skip this check if the selection begins within a list
  // This is to match the behaviour of the toolbar buttons being disabled

  if (!(0, _find.findFirstParentListNode)($from)) {
    for (var i = startIndex; i < endIndex; i++) {
      var position = nodeRangeAroundList.$from.posAtIndex(i, depth);
      var resolvedPosition = doc.resolve(position);
      var currentChild = parentNode.child(i);
      var currentNodeRange = resolvedPosition.blockRange(tr.doc.resolve(position + currentChild.nodeSize));

      if (currentNodeRange && !(0, _node.isListNode)(currentChild) && !(0, _prosemirrorTransform.findWrapping)(currentNodeRange, nextListNodeType)) {
        return;
      }
    }
  } // Checking for any non list nodes and wrapping them in a list
  // so they can be converted


  tr.doc.nodesBetween(nodeRangeAroundList.start, nodeRangeAroundList.end, function (node, pos) {
    // Skip over any nodes that are part of a list
    if ((0, _find.findFirstParentListNode)(tr.doc.resolve(tr.mapping.map(pos)))) {
      return false;
    } // The following applies to suitable nodes that are not within a list


    var currentNodeNotWrappedInList = node;
    var isNotAnEmptyParagraphAndIsParagraphOrLeafNode = !isEmptyParagraph(currentNodeNotWrappedInList) && (!node.type.isBlock || node.type.name === 'paragraph');

    if (isNotAnEmptyParagraphAndIsParagraphOrLeafNode) {
      var remainingNodeRange = new _prosemirrorModel.NodeRange(tr.doc.resolve(tr.mapping.map(pos)), tr.doc.resolve(tr.mapping.map(pos) + currentNodeNotWrappedInList.nodeSize), nodeRangeAroundList.depth);
      convertAroundList({
        tr: tr,
        nextListNodeType: nextListNodeType,
        nodeRange: remainingNodeRange
      });
      return false;
    }
  });
  convertSelectedList({
    tr: tr,
    nextListNodeType: nextListNodeType
  });

  if (tr.docChanged) {
    (0, _node.joinSiblingLists)({
      tr: tr,
      forceListType: nextListNodeType
    });
  }
}

var convertSelectedList = function convertSelectedList(_ref2) {
  var tr = _ref2.tr,
      nextListNodeType = _ref2.nextListNodeType;
  var selection = tr.selection,
      _tr$selection2 = tr.selection,
      from = _tr$selection2.from,
      to = _tr$selection2.to; // get the positions of all the leaf nodes within the selection

  var nodePositions = [];

  if (selection instanceof _prosemirrorState.TextSelection && selection.$cursor) {
    nodePositions.push(from);
  } else {
    // nodesBetween doesn't return leaf nodes that are outside of from and to
    tr.doc.nodesBetween(from, to, function (node, pos) {
      if (!node.isLeaf) {
        return true;
      }

      nodePositions.push(pos);
    });
  } // use those positions to get the closest parent list nodes


  nodePositions.reduce(function (acc, pos) {
    var closestParentListNode = (0, _prosemirrorUtils.findParentNodeClosestToPos)(tr.doc.resolve(pos), _node.isListNode);

    if (!closestParentListNode) {
      return acc;
    } // don't add duplicates if the parent has already been added into the array


    var existingParent = acc.find(function (node) {
      return node.pos === closestParentListNode.pos && node.start === closestParentListNode.start && node.depth === closestParentListNode.depth;
    });

    if (!existingParent) {
      acc.push(closestParentListNode);
    }

    return acc;
  }, []).forEach(function (item) {
    tr.setNodeMarkup(item.pos, nextListNodeType);
  });
};

var convertAroundList = function convertAroundList(_ref3) {
  var tr = _ref3.tr,
      nextListNodeType = _ref3.nextListNodeType,
      nodeRange = _ref3.nodeRange;

  for (var i = nodeRange.endIndex - 1; i >= nodeRange.startIndex; i--) {
    // @ts-ignore posAtIndex is a public API but has no type yet
    var position = nodeRange.$from.posAtIndex(i, nodeRange.depth);
    var resolvedPos = tr.doc.resolve(position + 1);
    var range = resolvedPos.blockRange(resolvedPos);

    if (!range) {
      return;
    }

    var wrappings = (0, _prosemirrorTransform.findWrapping)(range, nextListNodeType);

    if (!range || !wrappings) {
      return;
    }

    tr.wrap(range, wrappings);
  }
};