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; }
import { NodeSelection, Selection, TextSelection } from '@atlaskit/editor-prosemirror/state';
import { CellSelection } from '@atlaskit/editor-tables/cell-selection';
export function addParagraphAtEnd(tr) {
  var paragraph = tr.doc.type.schema.nodes.paragraph,
    doc = tr.doc;
  if (doc.lastChild && !(doc.lastChild.type === paragraph && doc.lastChild.content.size === 0)) {
    if (paragraph) {
      tr.insert(doc.content.size, paragraph.createAndFill());
    }
  }
  tr.setSelection(TextSelection.create(tr.doc, tr.doc.content.size - 1));
  tr.scrollIntoView();
}
export function createParagraphAtEnd() {
  return function (state, dispatch) {
    var tr = state.tr;
    addParagraphAtEnd(tr);
    if (dispatch) {
      dispatch(tr);
    }
    return true;
  };
}

// Remove this when cleaning up platform_editor_toolbar_aifc
// eslint-disable-next-line @repo/internal/deprecations/deprecation-ticket-required
/**
 *
 * @deprecated use changeImageAlignmentTr instead
 */
export var changeImageAlignment = function changeImageAlignment(align) {
  return function (state, dispatch) {
    var _state$selection = state.selection,
      from = _state$selection.from,
      to = _state$selection.to;
    var tr = state.tr;
    state.doc.nodesBetween(from, to, function (node, pos) {
      if (node.type === state.schema.nodes.mediaSingle) {
        tr.setNodeMarkup(pos, undefined, _objectSpread(_objectSpread({}, node.attrs), {}, {
          layout: align === 'center' ? 'center' : "align-".concat(align)
        }));
      }
    });
    if (tr.docChanged && dispatch) {
      dispatch(tr.scrollIntoView());
      return true;
    }
    return false;
  };
};
export var changeImageAlignmentNext = function changeImageAlignmentNext(align) {
  return function (tr) {
    var _tr$selection = tr.selection,
      from = _tr$selection.from,
      to = _tr$selection.to;
    var initialDoc = tr.doc;
    tr.doc.nodesBetween(from, to, function (node, pos) {
      if (node.type === tr.doc.type.schema.nodes.mediaSingle) {
        tr.setNodeMarkup(pos, undefined, _objectSpread(_objectSpread({}, node.attrs), {}, {
          layout: align === 'center' ? 'center' : "align-".concat(align)
        }));
      }
    });

    // compare tr.doc with initialDoc instead of tr.docChanged
    // because tr passed in might have been modified prior this function
    // e.g. see changeAlignmentTr platform/packages/editor/editor-plugin-alignment/src/editor-commands/index.ts:L197
    if (!tr.doc.eq(initialDoc)) {
      tr.scrollIntoView();
      return true;
    }
    return false;
  };
};

// Remove this when cleaning up platform_editor_toolbar_aifc
// eslint-disable-next-line @repo/internal/deprecations/deprecation-ticket-required
/**
 *
 * @deprecated use createToggleBlockMarkOnRangeNext instead, which does not require passing editorState
 */
export var createToggleBlockMarkOnRange = function createToggleBlockMarkOnRange(markType, getAttrs, allowedBlocks) {
  return function (from, to, tr, state) {
    var markApplied = false;
    state.doc.nodesBetween(from, to, function (node, pos, parent) {
      var _state$schema, _state$schema2, _state$schema3;
      if (!node.type.isBlock) {
        return false;
      }
      var parentAllowsMark = state !== null && state !== void 0 && (_state$schema = state.schema) !== null && _state$schema !== void 0 && (_state$schema = _state$schema.nodes) !== null && _state$schema !== void 0 && _state$schema.blockTaskItem && (parent === null || parent === void 0 ? void 0 : parent.type) === (state === null || state === void 0 || (_state$schema2 = state.schema) === null || _state$schema2 === void 0 || (_state$schema2 = _state$schema2.nodes) === null || _state$schema2 === void 0 ? void 0 : _state$schema2.blockTaskItem) && markType === (state === null || state === void 0 || (_state$schema3 = state.schema) === null || _state$schema3 === void 0 || (_state$schema3 = _state$schema3.marks) === null || _state$schema3 === void 0 ? void 0 : _state$schema3.indentation) ? false : parent === null || parent === void 0 ? void 0 : parent.type.allowsMarkType(markType);
      if ((!allowedBlocks || (Array.isArray(allowedBlocks) ? allowedBlocks.indexOf(node.type) > -1 : allowedBlocks(state.schema, node, parent))) && parentAllowsMark) {
        var oldMarks = node.marks.filter(function (mark) {
          return mark.type === markType;
        });
        var prevAttrs = oldMarks.length ? oldMarks[0].attrs : undefined;
        var newAttrs = getAttrs(prevAttrs, node);
        if (newAttrs !== undefined) {
          tr.setNodeMarkup(pos, node.type, node.attrs, node.marks.filter(function (mark) {
            return !markType.excludes(mark.type);
          }).concat(newAttrs === false ? [] : markType.create(newAttrs)));
          markApplied = true;
        }
      }
      return;
    });
    return markApplied;
  };
};
export var createToggleBlockMarkOnRangeNext = function createToggleBlockMarkOnRangeNext(markType, getAttrs, allowedBlocks) {
  return function (from, to, tr) {
    var markApplied = false;
    tr.doc.nodesBetween(from, to, function (node, pos, parent) {
      var _schema$nodes, _schema$nodes2, _schema$marks;
      if (!node.type.isBlock) {
        return false;
      }
      var schema = tr.doc.type.schema;
      var parentAllowsMark = schema !== null && schema !== void 0 && (_schema$nodes = schema.nodes) !== null && _schema$nodes !== void 0 && _schema$nodes.blockTaskItem && (parent === null || parent === void 0 ? void 0 : parent.type) === (schema === null || schema === void 0 || (_schema$nodes2 = schema.nodes) === null || _schema$nodes2 === void 0 ? void 0 : _schema$nodes2.blockTaskItem) && markType === (schema === null || schema === void 0 || (_schema$marks = schema.marks) === null || _schema$marks === void 0 ? void 0 : _schema$marks.indentation) ? false : parent === null || parent === void 0 ? void 0 : parent.type.allowsMarkType(markType);
      if ((!allowedBlocks || (Array.isArray(allowedBlocks) ? allowedBlocks.indexOf(node.type) > -1 : allowedBlocks(tr.doc.type.schema, node, parent))) && parentAllowsMark) {
        var oldMarks = node.marks.filter(function (mark) {
          return mark.type === markType;
        });
        var prevAttrs = oldMarks.length ? oldMarks[0].attrs : undefined;
        var newAttrs = getAttrs(prevAttrs, node);
        if (newAttrs !== undefined) {
          tr.setNodeMarkup(pos, node.type, node.attrs, node.marks.filter(function (mark) {
            return !markType.excludes(mark.type);
          }).concat(newAttrs === false ? [] : markType.create(newAttrs)));
          markApplied = true;
        }
      }
      return;
    });
    return markApplied;
  };
};
export var createToggleInlineMarkOnRange = function createToggleInlineMarkOnRange(markType, getAttrs) {
  return function (from, to, tr, state) {
    var markApplied = false;
    state.doc.nodesBetween(from, to, function (node, pos, parent) {
      if (parent !== null && parent !== void 0 && parent.type.allowsMarkType(markType)) {
        var oldMarks = node.marks.filter(function (mark) {
          return mark.type === markType;
        });
        var prevAttrs = oldMarks.length ? oldMarks[0].attrs : undefined;
        var newAttrs = getAttrs(prevAttrs, node);
        if (newAttrs !== undefined) {
          tr.setNodeMarkup(pos, node.type, node.attrs, node.marks.filter(function (mark) {
            return !markType.excludes(mark.type);
          }).concat(newAttrs === false ? [] : markType.create(newAttrs)));
          tr.setSelection(NodeSelection.create(tr.doc, state.selection.from));
          markApplied = true;
        }
      }
      return;
    });
    return markApplied;
  };
};

// Remove this when cleaning up platform_editor_toolbar_aifc
// eslint-disable-next-line @repo/internal/deprecations/deprecation-ticket-required
/**
 * @deprecated use toggleBlockMarkTr instead
 * Toggles block mark based on the return type of `getAttrs`.
 * This is similar to ProseMirror's `getAttrs` from `AttributeSpec`
 * return `false` to remove the mark.
 * return `undefined for no-op.
 * return an `object` to update the mark.
 */
export var toggleBlockMark = function toggleBlockMark(markType, getAttrs, allowedBlocks) {
  return function (state, dispatch) {
    var markApplied = false;
    var tr = state.tr;
    var toggleBlockMarkOnRange = createToggleBlockMarkOnRange(markType, getAttrs, allowedBlocks);
    if (state.selection instanceof CellSelection) {
      state.selection.forEachCell(function (cell, pos) {
        markApplied = toggleBlockMarkOnRange(pos, pos + cell.nodeSize, tr, state);
      });
    } else {
      var _state$selection2 = state.selection,
        from = _state$selection2.from,
        to = _state$selection2.to;
      markApplied = toggleBlockMarkOnRange(from, to, tr, state);
    }
    if (markApplied && tr.docChanged) {
      if (dispatch) {
        dispatch(tr.scrollIntoView());
      }
      return true;
    }
    return false;
  };
};

/**
 * Toggles block mark based on the return type of `getAttrs`.
 * @returns true if the mark is applied, false otherwise.
 */
export var toggleBlockMarkNext = function toggleBlockMarkNext(markType, getAttrs, allowedBlocks) {
  return function (tr) {
    var markApplied = false;
    var toggleBlockMarkOnRange = createToggleBlockMarkOnRangeNext(markType, getAttrs, allowedBlocks);
    var initialDoc = tr.doc;
    var selection = tr.selection;
    if (selection instanceof CellSelection) {
      selection.forEachCell(function (cell, pos) {
        markApplied = toggleBlockMarkOnRange(pos, pos + cell.nodeSize, tr);
      });
    } else {
      var from = selection.from,
        to = selection.to;
      markApplied = toggleBlockMarkOnRange(from, to, tr);
    }

    // compare tr.doc with initialDoc instead of tr.docChanged
    // because tr passed in might have been modified prior this function
    // e.g. see changeAlignmentTr platform/packages/editor/editor-plugin-alignment/src/editor-commands/index.ts:L197
    if (markApplied && !initialDoc.eq(tr.doc)) {
      tr.scrollIntoView();
      return true;
    }
    return false;
  };
};
export var clearEditorContent = function clearEditorContent(state, dispatch) {
  var tr = state.tr;
  tr.replace(0, state.doc.nodeSize - 2);
  tr.setSelection(Selection.atStart(tr.doc));
  if (dispatch) {
    dispatch(tr);
    return true;
  }
  return false;
};

// https://github.com/ProseMirror/prosemirror-commands/blob/master/src/commands.js#L90
// Keep going left up the tree, without going across isolating boundaries, until we
// can go along the tree at that same level
//
// You can think of this as, if you could construct each document like we do in the tests,
// return the position of the first ) backwards from the current selection.
export function findCutBefore($pos) {
  // parent is non-isolating, so we can look across this boundary
  if (!$pos.parent.type.spec.isolating) {
    // search up the tree from the pos's *parent*
    for (var i = $pos.depth - 1; i >= 0; i--) {
      // starting from the inner most node's parent, find out
      // if we're not its first child
      if ($pos.index(i) > 0) {
        return $pos.doc.resolve($pos.before(i + 1));
      }
      if ($pos.node(i).type.spec.isolating) {
        break;
      }
    }
  }
  return null;
}

// eslint-disable-next-line @repo/internal/deprecations/deprecation-ticket-required -- Ignored via go/ED-25883
/**
 * @deprecated
 *
 * This method is no longer needed and can be accessed via the
 * `editor-plugin-block-type` command of `setTextLevel`
 */
export function setHeading(level) {
  return function (state, dispatch) {
    var selection = state.selection,
      schema = state.schema,
      tr = state.tr;
    var ranges = selection instanceof CellSelection ? selection.ranges : [selection];
    ranges.forEach(function (_ref) {
      var $from = _ref.$from,
        $to = _ref.$to;
      tr.setBlockType($from.pos, $to.pos, schema.nodes.heading, {
        level: level
      });
    });
    if (dispatch) {
      dispatch(tr);
    }
    return true;
  };
}

// eslint-disable-next-line @atlaskit/editor/no-re-export
export { insertBlock } from './insert-block';