
import { __decorate, __param } from '../../../../../../../../external/tslib/tslib.es6.js';
import { localize } from '../../../../../nls.js';
import { $ as $$1, append, createElement, addStandardDisposableGenericMouseDownListener, addStandardDisposableGenericMouseUpListener, scheduleAtNextAnimationFrame } from '../../../../../base/browser/dom.js';
import { IStorageService } from '../../../../../platform/storage/common/storage.service.js';
import { ITelemetryService } from '../../../../../platform/telemetry/common/telemetry.service.js';
import { registerThemingParticipant } from '../../../../../platform/theme/common/themeService.js';
import { IThemeService } from '../../../../../platform/theme/common/themeService.service.js';
import { EditorPaneSelectionCompareResult, EditorPaneSelectionChangeReason } from '../../../../common/editor.js';
import { getDefaultNotebookCreationOptions } from '../notebookEditorWidget.js';
import { CancellationTokenSource } from '../../../../../base/common/cancellation.js';
import { SideBySideDiffElementViewModel } from './diffElementViewModel.js';
import { IInstantiationService } from '../../../../../platform/instantiation/common/instantiation.js';
import { CellDiffSingleSideRenderer, CellDiffSideBySideRenderer, CellDiffPlaceholderRenderer, NotebookDocumentMetadataDiffRenderer, NotebookTextDiffList, NotebookCellTextDiffListDelegate } from './notebookDiffList.js';
import { IContextKeyService } from '../../../../../platform/contextkey/common/contextkey.service.js';
import '../../../../../platform/theme/common/colorUtils.js';
import { foreground, focusBorder } from '../../../../../platform/theme/common/colors/baseColors.js';
import '../../../../../platform/theme/common/colors/chartsColors.js';
import { editorBackground, diffDiagonalFill } from '../../../../../platform/theme/common/colors/editorColors.js';
import '../../../../../platform/theme/common/colors/inputColors.js';
import '../../../../../platform/theme/common/colors/listColors.js';
import '../../../../../platform/theme/common/colors/menuColors.js';
import '../../../../../platform/theme/common/colors/minimapColors.js';
import '../../../../../platform/theme/common/colors/miscColors.js';
import '../../../../../platform/theme/common/colors/quickpickColors.js';
import '../../../../../platform/theme/common/colors/searchColors.js';
import { INotebookEditorWorkerService } from '../../common/services/notebookWorkerService.service.js';
import { IConfigurationService } from '../../../../../platform/configuration/common/configuration.service.js';
import { createBareFontInfoFromRawSettings } from '../../../../../editor/common/config/fontInfoFromSettings.js';
import { PixelRatio } from '../../../../../base/browser/pixelRatio.js';
import { DiffSide, DIFF_CELL_MARGIN } from './notebookDiffEditorBrowser.js';
import { Emitter, Event } from '../../../../../base/common/event.js';
import { DisposableStore, toDisposable } from '../../../../../base/common/lifecycle.js';
import { EditorPane } from '../../../../browser/parts/editor/editorPane.js';
import { NOTEBOOK_DIFF_EDITOR_ID, NotebookSetting, CellUri } from '../../common/notebookCommon.js';
import { SequencerByKey } from '../../../../../base/common/async.js';
import { generateUuid } from '../../../../../base/common/uuid.js';
import { BackLayerWebView } from '../view/renderers/backLayerWebView.js';
import { NotebookDiffEditorEventDispatcher, NotebookDiffLayoutChangedEvent } from './eventDispatcher.js';
import { FontMeasurements } from '../../../../../editor/browser/config/fontMeasurements.js';
import { NotebookOptions } from '../notebookOptions.js';
import { cellIndexesToRanges, cellRangesToIndexes } from '../../common/notebookRange.js';
import { NotebookDiffOverviewRuler } from './notebookDiffOverviewRuler.js';
import { registerZIndex, ZIndex } from '../../../../../platform/layout/browser/zIndexRegistry.js';
import { NotebookDiffViewModel } from './notebookDiffViewModel.js';
import { INotebookService } from '../../common/notebookService.service.js';
import { DiffEditorHeightCalculatorService } from './editorHeightCalculator.js';
import { IEditorService } from '../../../../services/editor/common/editorService.service.js';
import { NotebookInlineDiffWidget } from './inlineDiff/notebookInlineDiffWidget.js';
import '../../../../../base/common/observableInternal/index.js';
import { observableValue } from '../../../../../base/common/observableInternal/observables/observableValue.js';

var NotebookTextDiffEditor_1;
const $ = $$1;
class NotebookDiffEditorSelection {
    constructor(selections) {
        this.selections = selections;
    }
    compare(other) {
        if (!(other instanceof NotebookDiffEditorSelection)) {
            return EditorPaneSelectionCompareResult.DIFFERENT;
        }
        if (this.selections.length !== other.selections.length) {
            return EditorPaneSelectionCompareResult.DIFFERENT;
        }
        for (let i = 0; i < this.selections.length; i++) {
            if (this.selections[i] !== other.selections[i]) {
                return EditorPaneSelectionCompareResult.DIFFERENT;
            }
        }
        return EditorPaneSelectionCompareResult.IDENTICAL;
    }
    restore(options) {
        const notebookOptions = {
            cellSelections: cellIndexesToRanges(this.selections)
        };
        Object.assign(notebookOptions, options);
        return notebookOptions;
    }
}
let NotebookTextDiffEditor = class NotebookTextDiffEditor extends EditorPane {
    static {
        NotebookTextDiffEditor_1 = this;
    }
    static {
        this.ENTIRE_DIFF_OVERVIEW_WIDTH = 30;
    }
    static {
        this.ID = NOTEBOOK_DIFF_EDITOR_ID;
    }
    get textModel() {
        return this._model?.modified.notebook;
    }
    get inlineNotebookEditor() {
        if (this._inlineView) {
            return this.inlineDiffWidget?.editorWidget;
        }
        return undefined;
    }
    get notebookOptions() {
        return this._notebookOptions;
    }
    get isDisposed() {
        return this._isDisposed;
    }
    constructor(
        group,
        instantiationService,
        themeService,
        contextKeyService,
        notebookEditorWorkerService,
        configurationService,
        telemetryService,
        storageService,
        notebookService,
        editorService
    ) {
        super(
            NotebookTextDiffEditor_1.ID,
            group,
            telemetryService,
            themeService,
            storageService
        );
        this.instantiationService = instantiationService;
        this.contextKeyService = contextKeyService;
        this.notebookEditorWorkerService = notebookEditorWorkerService;
        this.configurationService = configurationService;
        this.notebookService = notebookService;
        this.editorService = editorService;
        this.creationOptions = getDefaultNotebookCreationOptions();
        this._dimension = undefined;
        this._modifiedWebview = null;
        this._originalWebview = null;
        this._webviewTransparentCover = null;
        this._inlineView = false;
        this._onMouseUp = this._register(( new Emitter()));
        this.onMouseUp = this._onMouseUp.event;
        this._onDidScroll = this._register(( new Emitter()));
        this.onDidScroll = this._onDidScroll.event;
        this.onDidChangeScroll = this._onDidScroll.event;
        this._model = null;
        this._modifiedResourceDisposableStore = this._register(( new DisposableStore()));
        this._insetModifyQueueByOutputId = ( new SequencerByKey());
        this._onDidDynamicOutputRendered = this._register(( new Emitter()));
        this.onDidDynamicOutputRendered = this._onDidDynamicOutputRendered.event;
        this._localStore = this._register(( new DisposableStore()));
        this._onDidChangeSelection = this._register(( new Emitter()));
        this.onDidChangeSelection = this._onDidChangeSelection.event;
        this._isDisposed = false;
        this._currentChangedIndex = observableValue(this, -1);
        this.currentChangedIndex = this._currentChangedIndex;
        this.pendingLayouts = ( new WeakMap());
        this.diffEditorCalcuator = this.instantiationService.createInstance(DiffEditorHeightCalculatorService, this.fontInfo.lineHeight);
        this._notebookOptions = instantiationService.createInstance(NotebookOptions, this.window, false, undefined);
        this._register(this._notebookOptions);
        this._revealFirst = true;
    }
    get fontInfo() {
        if (!this._fontInfo) {
            this._fontInfo = this.createFontInfo();
        }
        return this._fontInfo;
    }
    createFontInfo() {
        const editorOptions = this.configurationService.getValue("editor");
        return FontMeasurements.readFontInfo(
            this.window,
            createBareFontInfoFromRawSettings(editorOptions, PixelRatio.getInstance(this.window).value)
        );
    }
    isOverviewRulerEnabled() {
        return this.configurationService.getValue(NotebookSetting.diffOverviewRuler) ?? false;
    }
    getSelection() {
        const selections = this._list.getFocus();
        return ( new NotebookDiffEditorSelection(selections));
    }
    toggleNotebookCellSelection(cell) {}
    updatePerformanceMetadata(cellId, executionId, duration, rendererId) {}
    async focusNotebookCell(cell, focus) {}
    async focusNextNotebookCell(cell, focus) {}
    didFocusOutputInputChange(inputFocused) {}
    getScrollTop() {
        return this._list?.scrollTop ?? 0;
    }
    getScrollHeight() {
        return this._list?.scrollHeight ?? 0;
    }
    getScrollPosition() {
        return {
            scrollTop: this.getScrollTop(),
            scrollLeft: this._list?.scrollLeft ?? 0
        };
    }
    setScrollPosition(scrollPosition) {
        if (!this._list) {
            return;
        }
        this._list.scrollTop = scrollPosition.scrollTop;
        if (scrollPosition.scrollLeft !== undefined) {
            this._list.scrollLeft = scrollPosition.scrollLeft;
        }
    }
    delegateVerticalScrollbarPointerDown(browserEvent) {
        this._list?.delegateVerticalScrollbarPointerDown(browserEvent);
    }
    updateOutputHeight(cellInfo, output, outputHeight, isInit) {
        const diffElement = cellInfo.diffElement;
        const cell = this.getCellByInfo(cellInfo);
        const outputIndex = cell.outputsViewModels.indexOf(output);
        if (diffElement instanceof SideBySideDiffElementViewModel) {
            const info = CellUri.parse(cellInfo.cellUri);
            if (!info) {
                return;
            }
            diffElement.updateOutputHeight(( info.notebook.toString()) === this._model?.original.resource.toString() ? DiffSide.Original : DiffSide.Modified, outputIndex, outputHeight);
        } else {
            diffElement.updateOutputHeight(
                diffElement.type === "insert" ? DiffSide.Modified : DiffSide.Original,
                outputIndex,
                outputHeight
            );
        }
        if (isInit) {
            this._onDidDynamicOutputRendered.fire({
                cell,
                output
            });
        }
    }
    setMarkupCellEditState(cellId, editState) {}
    didStartDragMarkupCell(cellId, event) {}
    didDragMarkupCell(cellId, event) {}
    didEndDragMarkupCell(cellId) {}
    didDropMarkupCell(cellId) {}
    didResizeOutput(cellId) {}
    async toggleInlineView() {
        this._layoutCancellationTokenSource?.dispose();
        this._inlineView = !this._inlineView;
        if (!this._lastLayoutProperties) {
            return;
        }
        if (this._inlineView) {
            this.layout(
                this._lastLayoutProperties?.dimension,
                this._lastLayoutProperties?.position
            );
            this.inlineDiffWidget?.show(
                this.input,
                this._model?.modified.notebook,
                this._model?.original.notebook,
                this._options
            );
        } else {
            this.layout(
                this._lastLayoutProperties?.dimension,
                this._lastLayoutProperties?.position
            );
            this.inlineDiffWidget?.hide();
        }
        this._layoutCancellationTokenSource = ( new CancellationTokenSource());
        this.updateLayout(this._layoutCancellationTokenSource.token);
    }
    createEditor(parent) {
        this._rootElement = append(parent, $$1(".notebook-text-diff-editor"));
        this._overflowContainer = createElement("div");
        this._overflowContainer.classList.add("notebook-overflow-widget-container", "monaco-editor");
        append(parent, this._overflowContainer);
        const renderers = [
            this.instantiationService.createInstance(CellDiffSingleSideRenderer, this),
            this.instantiationService.createInstance(CellDiffSideBySideRenderer, this),
            this.instantiationService.createInstance(CellDiffPlaceholderRenderer, this),
            this.instantiationService.createInstance(NotebookDocumentMetadataDiffRenderer, this)
        ];
        this._listViewContainer = append(this._rootElement, $$1(".notebook-diff-list-view"));
        this._list = this.instantiationService.createInstance(
            NotebookTextDiffList,
            "NotebookTextDiff",
            this._listViewContainer,
            this.instantiationService.createInstance(NotebookCellTextDiffListDelegate, this.window),
            renderers,
            this.contextKeyService,
            {
                setRowLineHeight: false,
                setRowHeight: false,
                supportDynamicHeights: true,
                horizontalScrolling: false,
                keyboardSupport: false,
                mouseSupport: true,
                multipleSelectionSupport: false,
                typeNavigationEnabled: true,
                paddingBottom: 0,
                styleController: _suffix => {
                    return this._list;
                },
                overrideStyles: {
                    listBackground: editorBackground,
                    listActiveSelectionBackground: editorBackground,
                    listActiveSelectionForeground: foreground,
                    listFocusAndSelectionBackground: editorBackground,
                    listFocusAndSelectionForeground: foreground,
                    listFocusBackground: editorBackground,
                    listFocusForeground: foreground,
                    listHoverForeground: foreground,
                    listHoverBackground: editorBackground,
                    listHoverOutline: focusBorder,
                    listFocusOutline: focusBorder,
                    listInactiveSelectionBackground: editorBackground,
                    listInactiveSelectionForeground: foreground,
                    listInactiveFocusBackground: editorBackground,
                    listInactiveFocusOutline: editorBackground
                },
                accessibilityProvider: {
                    getAriaLabel() {
                        return null;
                    },
                    getWidgetAriaLabel() {
                        return localize(11168, "Notebook Text Diff");
                    }
                }
            }
        );
        this.inlineDiffWidget = this._register(this.instantiationService.createInstance(
            NotebookInlineDiffWidget,
            this._rootElement,
            this.group.id,
            this.window,
            this.notebookOptions,
            this._dimension
        ));
        this._register(this._list);
        this._register(this._list.onMouseUp(e => {
            if (e.element) {
                if (typeof e.index === "number") {
                    this._list.setFocus([e.index]);
                }
                this._onMouseUp.fire({
                    event: e.browserEvent,
                    target: e.element
                });
            }
        }));
        this._register(this._list.onDidScroll(() => {
            this._onDidScroll.fire();
        }));
        this._register(this._list.onDidChangeFocus(() => this._onDidChangeSelection.fire({
            reason: EditorPaneSelectionChangeReason.USER
        })));
        this._overviewRulerContainer = createElement("div");
        this._overviewRulerContainer.classList.add("notebook-overview-ruler-container");
        this._rootElement.appendChild(this._overviewRulerContainer);
        this._registerOverviewRuler();
        this._webviewTransparentCover = append(this._list.rowsContainer, $(".webview-cover"));
        this._webviewTransparentCover.style.display = "none";
        this._register(
            addStandardDisposableGenericMouseDownListener(this._overflowContainer, e => {
                if (e.target.classList.contains("slider") && this._webviewTransparentCover) {
                    this._webviewTransparentCover.style.display = "block";
                }
            })
        );
        this._register(
            addStandardDisposableGenericMouseUpListener(this._overflowContainer, () => {
                if (this._webviewTransparentCover) {
                    this._webviewTransparentCover.style.display = "none";
                }
            })
        );
        this._register(this._list.onDidScroll(e => {
            this._webviewTransparentCover.style.top = `${e.scrollTop}px`;
        }));
    }
    _registerOverviewRuler() {
        this._overviewRuler = this._register(this.instantiationService.createInstance(
            NotebookDiffOverviewRuler,
            this,
            NotebookTextDiffEditor_1.ENTIRE_DIFF_OVERVIEW_WIDTH,
            this._overviewRulerContainer
        ));
    }
    _updateOutputsOffsetsInWebview(scrollTop, scrollHeight, activeWebview, getActiveNestedCell, diffSide) {
        activeWebview.element.style.height = `${scrollHeight}px`;
        if (activeWebview.insetMapping) {
            const updateItems = [];
            const removedItems = [];
            activeWebview.insetMapping.forEach((value, key) => {
                const cell = getActiveNestedCell(value.cellInfo.diffElement);
                if (!cell) {
                    return;
                }
                const viewIndex = this._list.indexOf(value.cellInfo.diffElement);
                if (viewIndex === undefined) {
                    return;
                }
                if (cell.outputsViewModels.indexOf(key) < 0) {
                    removedItems.push(key);
                } else {
                    const cellTop = this._list.getCellViewScrollTop(value.cellInfo.diffElement);
                    const outputIndex = cell.outputsViewModels.indexOf(key);
                    const outputOffset = value.cellInfo.diffElement.getOutputOffsetInCell(diffSide, outputIndex);
                    updateItems.push({
                        cell,
                        output: key,
                        cellTop: cellTop,
                        outputOffset: outputOffset,
                        forceDisplay: false
                    });
                }
            });
            activeWebview.removeInsets(removedItems);
            if (updateItems.length) {
                activeWebview.updateScrollTops(updateItems, []);
            }
        }
    }
    async setInput(input, options, context, token) {
        this.inlineDiffWidget?.hide();
        await super.setInput(input, options, context, token);
        const model = await input.resolve();
        if (this._model !== model) {
            this._detachModel();
            this._attachModel(model);
        }
        this._model = model;
        if (this._model === null) {
            return;
        }
        if (this._inlineView) {
            this._listViewContainer.style.display = "none";
            this.inlineDiffWidget?.show(input, model.modified.notebook, model.original.notebook, options);
        } else {
            this._listViewContainer.style.display = "block";
            this.inlineDiffWidget?.hide();
        }
        this._revealFirst = true;
        this._modifiedResourceDisposableStore.clear();
        this._layoutCancellationTokenSource = ( new CancellationTokenSource());
        this._modifiedResourceDisposableStore.add(Event.any(
            this._model.original.notebook.onDidChangeContent,
            this._model.modified.notebook.onDidChangeContent
        )(e => {
            if (this._model !== null && this.editorService.activeEditor !== input) {
                this._layoutCancellationTokenSource?.dispose();
                this._layoutCancellationTokenSource = ( new CancellationTokenSource());
                this.updateLayout(this._layoutCancellationTokenSource.token);
            }
        }));
        await this._createOriginalWebview(
            generateUuid(),
            this._model.original.viewType,
            this._model.original.resource
        );
        if (this._originalWebview) {
            this._modifiedResourceDisposableStore.add(this._originalWebview);
        }
        await this._createModifiedWebview(
            generateUuid(),
            this._model.modified.viewType,
            this._model.modified.resource
        );
        if (this._modifiedWebview) {
            this._modifiedResourceDisposableStore.add(this._modifiedWebview);
        }
        await this.updateLayout(
            this._layoutCancellationTokenSource.token,
            options?.cellSelections ? cellRangesToIndexes(options.cellSelections) : undefined
        );
    }
    setVisible(visible) {
        super.setVisible(visible);
        if (!visible) {
            this.inlineDiffWidget?.hide();
        }
    }
    _detachModel() {
        this._localStore.clear();
        this._originalWebview?.dispose();
        this._originalWebview?.element.remove();
        this._originalWebview = null;
        this._modifiedWebview?.dispose();
        this._modifiedWebview?.element.remove();
        this._modifiedWebview = null;
        this.notebookDiffViewModel?.dispose();
        this.notebookDiffViewModel = undefined;
        this._modifiedResourceDisposableStore.clear();
        this._list.clear();
    }
    _attachModel(model) {
        this._model = model;
        this._eventDispatcher = ( new NotebookDiffEditorEventDispatcher());
        const updateInsets = () => {
            scheduleAtNextAnimationFrame(this.window, () => {
                if (this._isDisposed) {
                    return;
                }
                if (this._modifiedWebview) {
                    this._updateOutputsOffsetsInWebview(
                        this._list.scrollTop,
                        this._list.scrollHeight,
                        this._modifiedWebview,
                        diffElement => {
                            return diffElement.modified;
                        },
                        DiffSide.Modified
                    );
                }
                if (this._originalWebview) {
                    this._updateOutputsOffsetsInWebview(
                        this._list.scrollTop,
                        this._list.scrollHeight,
                        this._originalWebview,
                        diffElement => {
                            return diffElement.original;
                        },
                        DiffSide.Original
                    );
                }
            });
        };
        this._localStore.add(this._list.onDidChangeContentHeight(() => {
            updateInsets();
        }));
        this._localStore.add(this._list.onDidChangeFocus(e => {
            if (e.indexes.length && this.notebookDiffViewModel && e.indexes[0] < this.notebookDiffViewModel.items.length) {
                const selectedItem = this.notebookDiffViewModel.items[e.indexes[0]];
                const changedItems = this.notebookDiffViewModel.items.filter(
                    item => item.type !== "unchanged" && item.type !== "unchangedMetadata" && item.type !== "placeholder"
                );
                if (selectedItem && selectedItem?.type !== "placeholder" && selectedItem?.type !== "unchanged" && selectedItem?.type !== "unchangedMetadata") {
                    return this._currentChangedIndex.set(changedItems.indexOf(selectedItem), undefined);
                }
            }
            return this._currentChangedIndex.set(-1, undefined);
        }));
        this._localStore.add(this._eventDispatcher.onDidChangeCellLayout(() => {
            updateInsets();
        }));
        const vm = this.notebookDiffViewModel = this._register(( new NotebookDiffViewModel(
            this._model,
            this.notebookEditorWorkerService,
            this.configurationService,
            this._eventDispatcher,
            this.notebookService,
            this.diffEditorCalcuator,
            this.fontInfo,
            undefined
        )));
        this._localStore.add(this.notebookDiffViewModel.onDidChangeItems(e => {
            this._originalWebview?.removeInsets([...this._originalWebview?.insetMapping.keys()]);
            this._modifiedWebview?.removeInsets([...this._modifiedWebview?.insetMapping.keys()]);
            if (this._revealFirst && typeof e.firstChangeIndex === "number" && e.firstChangeIndex > -1 && e.firstChangeIndex < this._list.length) {
                this._revealFirst = false;
                this._list.setFocus([e.firstChangeIndex]);
                this._list.reveal(e.firstChangeIndex, 0.3);
            }
            this._list.splice(e.start, e.deleteCount, e.elements);
            if (this.isOverviewRulerEnabled()) {
                this._overviewRuler.updateViewModels(vm.items, this._eventDispatcher);
            }
        }));
    }
    async _createModifiedWebview(id, viewType, resource) {
        this._modifiedWebview?.dispose();
        this._modifiedWebview = this.instantiationService.createInstance(BackLayerWebView, this, id, viewType, resource, {
            ...this._notebookOptions.computeDiffWebviewOptions(),
            fontFamily: this._generateFontFamily()
        }, undefined);
        this._list.rowsContainer.insertAdjacentElement("afterbegin", this._modifiedWebview.element);
        this._modifiedWebview.createWebview(this.window);
        this._modifiedWebview.element.style.width = `calc(50% - 16px)`;
        this._modifiedWebview.element.style.left = `calc(50%)`;
    }
    _generateFontFamily() {
        return this.fontInfo.fontFamily ?? `"SF Mono", Monaco, Menlo, Consolas, "Ubuntu Mono", "Liberation Mono", "DejaVu Sans Mono", "Courier New", monospace`;
    }
    async _createOriginalWebview(id, viewType, resource) {
        this._originalWebview?.dispose();
        this._originalWebview = this.instantiationService.createInstance(BackLayerWebView, this, id, viewType, resource, {
            ...this._notebookOptions.computeDiffWebviewOptions(),
            fontFamily: this._generateFontFamily()
        }, undefined);
        this._list.rowsContainer.insertAdjacentElement("afterbegin", this._originalWebview.element);
        this._originalWebview.createWebview(this.window);
        this._originalWebview.element.style.width = `calc(50% - 16px)`;
        this._originalWebview.element.style.left = `16px`;
    }
    setOptions(options) {
        const selections = options?.cellSelections ? cellRangesToIndexes(options.cellSelections) : undefined;
        if (selections) {
            this._list.setFocus(selections);
        }
    }
    async updateLayout(token, selections) {
        if (!this._model || !this.notebookDiffViewModel) {
            return;
        }
        await this.notebookDiffViewModel.computeDiff(token);
        if (token.isCancellationRequested) {
            return;
        }
        if (selections) {
            this._list.setFocus(selections);
        }
    }
    scheduleOutputHeightAck(cellInfo, outputId, height) {
        const diffElement = cellInfo.diffElement;
        let diffSide = DiffSide.Original;
        if (diffElement instanceof SideBySideDiffElementViewModel) {
            const info = CellUri.parse(cellInfo.cellUri);
            if (!info) {
                return;
            }
            diffSide = ( info.notebook.toString()) === this._model?.original.resource.toString() ? DiffSide.Original : DiffSide.Modified;
        } else {
            diffSide = diffElement.type === "insert" ? DiffSide.Modified : DiffSide.Original;
        }
        const webview = diffSide === DiffSide.Modified ? this._modifiedWebview : this._originalWebview;
        scheduleAtNextAnimationFrame(this.window, () => {
            webview?.ackHeight([{
                cellId: cellInfo.cellId,
                outputId,
                height
            }]);
        }, 10);
    }
    layoutNotebookCell(cell, height) {
        const relayout = (cell, height) => {
            this._list.updateElementHeight2(cell, height);
        };
        let disposable = this.pendingLayouts.get(cell);
        if (disposable) {
            this._localStore.delete(disposable);
        }
        let r;
        const layoutDisposable = scheduleAtNextAnimationFrame(this.window, () => {
            this.pendingLayouts.delete(cell);
            relayout(cell, height);
            r();
        });
        disposable = toDisposable(() => {
            layoutDisposable.dispose();
            r();
        });
        this._localStore.add(disposable);
        this.pendingLayouts.set(cell, disposable);
        return ( new Promise(resolve => {
            r = resolve;
        }));
    }
    setScrollTop(scrollTop) {
        this._list.scrollTop = scrollTop;
    }
    triggerScroll(event) {
        this._list.triggerScrollFromMouseWheelEvent(event);
    }
    firstChange() {
        if (!this.notebookDiffViewModel) {
            return;
        }
        const currentViewModels = this.notebookDiffViewModel.items;
        const index = currentViewModels.findIndex(
            vm => vm.type !== "unchanged" && vm.type !== "unchangedMetadata" && vm.type !== "placeholder"
        );
        if (index >= 0) {
            this._list.setFocus([index]);
            this._list.reveal(index);
        }
    }
    lastChange() {
        if (!this.notebookDiffViewModel) {
            return;
        }
        const currentViewModels = this.notebookDiffViewModel.items;
        const item = currentViewModels.slice().reverse().find(
            vm => vm.type !== "unchanged" && vm.type !== "unchangedMetadata" && vm.type !== "placeholder"
        );
        const index = item ? currentViewModels.indexOf(item) : -1;
        if (index >= 0) {
            this._list.setFocus([index]);
            this._list.reveal(index);
        }
    }
    previousChange() {
        if (!this.notebookDiffViewModel) {
            return;
        }
        let currFocus = this._list.getFocus()[0];
        if (isNaN(currFocus) || currFocus < 0) {
            currFocus = 0;
        }
        let prevChangeIndex = currFocus - 1;
        const currentViewModels = this.notebookDiffViewModel.items;
        while (prevChangeIndex >= 0) {
            const vm = currentViewModels[prevChangeIndex];
            if (vm.type !== "unchanged" && vm.type !== "unchangedMetadata" && vm.type !== "placeholder") {
                break;
            }
            prevChangeIndex--;
        }
        if (prevChangeIndex >= 0) {
            this._list.setFocus([prevChangeIndex]);
            this._list.reveal(prevChangeIndex);
        } else {
            const index = currentViewModels.findLastIndex(
                vm => vm.type !== "unchanged" && vm.type !== "unchangedMetadata" && vm.type !== "placeholder"
            );
            if (index >= 0) {
                this._list.setFocus([index]);
                this._list.reveal(index);
            }
        }
    }
    nextChange() {
        if (!this.notebookDiffViewModel) {
            return;
        }
        let currFocus = this._list.getFocus()[0];
        if (isNaN(currFocus) || currFocus < 0) {
            currFocus = 0;
        }
        let nextChangeIndex = currFocus + 1;
        const currentViewModels = this.notebookDiffViewModel.items;
        while (nextChangeIndex < currentViewModels.length) {
            const vm = currentViewModels[nextChangeIndex];
            if (vm.type !== "unchanged" && vm.type !== "unchangedMetadata" && vm.type !== "placeholder") {
                break;
            }
            nextChangeIndex++;
        }
        if (nextChangeIndex < currentViewModels.length) {
            this._list.setFocus([nextChangeIndex]);
            this._list.reveal(nextChangeIndex);
        } else {
            const index = currentViewModels.findIndex(
                vm => vm.type !== "unchanged" && vm.type !== "unchangedMetadata" && vm.type !== "placeholder"
            );
            if (index >= 0) {
                this._list.setFocus([index]);
                this._list.reveal(index);
            }
        }
    }
    createOutput(cellDiffViewModel, cellViewModel, output, getOffset, diffSide) {
        this._insetModifyQueueByOutputId.queue(
            output.source.model.outputId + (diffSide === DiffSide.Modified ? "-right" : "left"),
            async () => {
                const activeWebview = diffSide === DiffSide.Modified ? this._modifiedWebview : this._originalWebview;
                if (!activeWebview) {
                    return;
                }
                if (!( activeWebview.insetMapping.has(output.source))) {
                    const cellTop = this._list.getCellViewScrollTop(cellDiffViewModel);
                    await activeWebview.createOutput({
                        diffElement: cellDiffViewModel,
                        cellHandle: cellViewModel.handle,
                        cellId: cellViewModel.id,
                        cellUri: cellViewModel.uri
                    }, output, cellTop, getOffset());
                } else {
                    const cellTop = this._list.getCellViewScrollTop(cellDiffViewModel);
                    const outputIndex = cellViewModel.outputsViewModels.indexOf(output.source);
                    const outputOffset = cellDiffViewModel.getOutputOffsetInCell(diffSide, outputIndex);
                    activeWebview.updateScrollTops([{
                        cell: cellViewModel,
                        output: output.source,
                        cellTop,
                        outputOffset,
                        forceDisplay: true
                    }], []);
                }
            }
        );
    }
    updateMarkupCellHeight() {}
    getCellByInfo(cellInfo) {
        return cellInfo.diffElement.getCellByUri(cellInfo.cellUri);
    }
    getCellById(cellId) {
        throw ( new Error("Not implemented"));
    }
    removeInset(cellDiffViewModel, cellViewModel, displayOutput, diffSide) {
        this._insetModifyQueueByOutputId.queue(
            displayOutput.model.outputId + (diffSide === DiffSide.Modified ? "-right" : "left"),
            async () => {
                const activeWebview = diffSide === DiffSide.Modified ? this._modifiedWebview : this._originalWebview;
                if (!activeWebview) {
                    return;
                }
                if (!( activeWebview.insetMapping.has(displayOutput))) {
                    return;
                }
                activeWebview.removeInsets([displayOutput]);
            }
        );
    }
    showInset(cellDiffViewModel, cellViewModel, displayOutput, diffSide) {
        this._insetModifyQueueByOutputId.queue(
            displayOutput.model.outputId + (diffSide === DiffSide.Modified ? "-right" : "left"),
            async () => {
                const activeWebview = diffSide === DiffSide.Modified ? this._modifiedWebview : this._originalWebview;
                if (!activeWebview) {
                    return;
                }
                if (!( activeWebview.insetMapping.has(displayOutput))) {
                    return;
                }
                const cellTop = this._list.getCellViewScrollTop(cellDiffViewModel);
                const outputIndex = cellViewModel.outputsViewModels.indexOf(displayOutput);
                const outputOffset = cellDiffViewModel.getOutputOffsetInCell(diffSide, outputIndex);
                activeWebview.updateScrollTops([{
                    cell: cellViewModel,
                    output: displayOutput,
                    cellTop,
                    outputOffset,
                    forceDisplay: true
                }], []);
            }
        );
    }
    hideInset(cellDiffViewModel, cellViewModel, output) {
        this._modifiedWebview?.hideInset(output);
        this._originalWebview?.hideInset(output);
    }
    getDomNode() {
        return this._rootElement;
    }
    getOverflowContainerDomNode() {
        return this._overflowContainer;
    }
    getControl() {
        return this;
    }
    clearInput() {
        this.inlineDiffWidget?.hide();
        super.clearInput();
        this._modifiedResourceDisposableStore.clear();
        this._list?.splice(0, this._list?.length || 0);
        this._model = null;
        this.notebookDiffViewModel?.dispose();
        this.notebookDiffViewModel = undefined;
    }
    deltaCellOutputContainerClassNames(diffSide, cellId, added, removed) {
        if (diffSide === DiffSide.Original) {
            this._originalWebview?.deltaCellOutputContainerClassNames(cellId, added, removed);
        } else {
            this._modifiedWebview?.deltaCellOutputContainerClassNames(cellId, added, removed);
        }
    }
    getLayoutInfo() {
        if (!this._list) {
            throw ( new Error("Editor is not initalized successfully"));
        }
        return {
            width: this._dimension.width,
            height: this._dimension.height,
            fontInfo: this.fontInfo,
            scrollHeight: this._list?.getScrollHeight() ?? 0,
            stickyHeight: 0,
            listViewOffsetTop: 0
        };
    }
    layout(dimension, position) {
        this._rootElement.classList.toggle("mid-width", dimension.width < 1000 && dimension.width >= 600);
        this._rootElement.classList.toggle("narrow-width", dimension.width < 600);
        const overviewRulerEnabled = this.isOverviewRulerEnabled();
        this._dimension = dimension.with(
            dimension.width - (overviewRulerEnabled ? NotebookTextDiffEditor_1.ENTIRE_DIFF_OVERVIEW_WIDTH : 0)
        );
        this._listViewContainer.style.height = `${dimension.height}px`;
        this._listViewContainer.style.width = `${this._dimension.width}px`;
        if (this._inlineView) {
            this._listViewContainer.style.display = "none";
            this.inlineDiffWidget?.setLayout(dimension, position);
        } else {
            this.inlineDiffWidget?.hide();
            this._listViewContainer.style.display = "block";
            this._list?.layout(this._dimension.height, this._dimension.width);
            if (this._modifiedWebview) {
                this._modifiedWebview.element.style.width = `calc(50% - 16px)`;
                this._modifiedWebview.element.style.left = `calc(50%)`;
            }
            if (this._originalWebview) {
                this._originalWebview.element.style.width = `calc(50% - 16px)`;
                this._originalWebview.element.style.left = `16px`;
            }
            if (this._webviewTransparentCover) {
                this._webviewTransparentCover.style.height = `${this._dimension.height}px`;
                this._webviewTransparentCover.style.width = `${this._dimension.width}px`;
            }
            if (overviewRulerEnabled) {
                this._overviewRuler.layout();
            }
        }
        this._lastLayoutProperties = {
            dimension,
            position
        };
        this._eventDispatcher?.emit([( new NotebookDiffLayoutChangedEvent({
            width: true,
            fontInfo: true
        }, this.getLayoutInfo()))]);
    }
    dispose() {
        this._isDisposed = true;
        this._layoutCancellationTokenSource?.dispose();
        this._detachModel();
        super.dispose();
    }
};
NotebookTextDiffEditor = NotebookTextDiffEditor_1 = ( __decorate([( __param(1, IInstantiationService)), ( __param(2, IThemeService)), ( __param(3, IContextKeyService)), ( __param(4, INotebookEditorWorkerService)), ( __param(5, IConfigurationService)), ( __param(6, ITelemetryService)), ( __param(7, IStorageService)), ( __param(8, INotebookService)), ( __param(9, IEditorService))], NotebookTextDiffEditor));
registerZIndex(ZIndex.Base, 10, "notebook-diff-view-viewport-slider");
registerThemingParticipant((theme, collector) => {
    const diffDiagonalFillColor = theme.getColor(diffDiagonalFill);
    collector.addRule(`
    .notebook-text-diff-editor .diagonal-fill {
        background-image: linear-gradient(
            -45deg,
            ${diffDiagonalFillColor} 12.5%,
            #0000 12.5%, #0000 50%,
            ${diffDiagonalFillColor} 50%, ${diffDiagonalFillColor} 62.5%,
            #0000 62.5%, #0000 100%
        );
        background-size: 8px 8px;
    }
    `);
    collector.addRule(`.notebook-text-diff-editor .cell-body { margin: ${DIFF_CELL_MARGIN}px; }`);
    collector.addRule(
        `.notebook-text-diff-editor .cell-placeholder-body { margin: ${DIFF_CELL_MARGIN}px 0; }`
    );
});

export { NotebookTextDiffEditor };
