src/vs/workbench/contrib/notebook/browser/view/cellParts/cellDnd.ts/performCellDropEdits
export function performCellDropEdits(editor: INotebookEditorDelegate, draggedCell: ICellViewModel, dropDirection: 'above' | 'below', draggedOverCell: ICellViewModel): void {
	const draggedCellIndex = editor.getCellIndex(draggedCell)!;
	let originalToIdx = editor.getCellIndex(draggedOverCell)!;

	if (typeof draggedCellIndex !== 'number' || typeof originalToIdx !== 'number') {
		return;
	}

	// If dropped on a folded markdown range, insert after the folding range
	if (dropDirection === 'below') {
		const newIdx = editor.getNextVisibleCellIndex(originalToIdx) ?? originalToIdx;
		originalToIdx = newIdx;
	}

	let selections = editor.getSelections();
	if (!selections.length) {
		selections = [editor.getFocus()];
	}

	let originalFocusIdx = editor.getFocus().start;

	// If the dragged cell is not focused/selected, ignore the current focus/selection and use the dragged idx
	if (!selections.some(s => s.start <= draggedCellIndex && s.end > draggedCellIndex)) {
		selections = [{ start: draggedCellIndex, end: draggedCellIndex + 1 }];
		originalFocusIdx = draggedCellIndex;
	}

	const droppedInSelection = selections.find(range => range.start <= originalToIdx && range.end > originalToIdx);
	if (droppedInSelection) {
		originalToIdx = droppedInSelection.start;
	}


	let numCells = 0;
	let focusNewIdx = originalToIdx;
	let newInsertionIdx = originalToIdx;

	// Compute a set of edits which will be applied in reverse order by the notebook text model.
	// `index`: the starting index of the range, after previous edits have been applied
	// `newIdx`: the destination index, after this edit's range has been removed
	selections.sort((a, b) => b.start - a.start);
	const edits = selections.map(range => {
		const length = range.end - range.start;

		// If this range is before the insertion point, subtract the cells in this range from the "to" index
		let toIndexDelta = 0;
		if (range.end <= newInsertionIdx) {
			toIndexDelta = -length;
		}

		const newIdx = newInsertionIdx + toIndexDelta;

		// If this range contains the focused cell, set the new focus index to the new index of the cell
		if (originalFocusIdx >= range.start && originalFocusIdx <= range.end) {
			const offset = originalFocusIdx - range.start;
			focusNewIdx = newIdx + offset;
		}

		// If below the insertion point, the original index will have been shifted down
		const fromIndexDelta = range.start >= originalToIdx ? numCells : 0;

		const edit: ICellMoveEdit = {
			editType: CellEditType.Move,
			index: range.start + fromIndexDelta,
			length,
			newIdx
		};
		numCells += length;

		// If a range was moved down, the insertion index needs to be adjusted
		if (range.end < newInsertionIdx) {
			newInsertionIdx -= length;
		}

		return edit;
	});

	const lastEdit = edits[edits.length - 1];
	const finalSelection = { start: lastEdit.newIdx, end: lastEdit.newIdx + numCells };
	const finalFocus = { start: focusNewIdx, end: focusNewIdx + 1 };

	editor.textModel!.applyEdits(
		edits,
		true,
		{ kind: SelectionStateType.Index, focus: editor.getFocus(), selections: editor.getSelections() },
		() => ({ kind: SelectionStateType.Index, focus: finalFocus, selections: [finalSelection] }),
		undefined, true);
	editor.revealCellRangeInView(finalSelection);
}