/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
import { $, h, reset } from '../../../../base/browser/dom.js';
import { renderLabelWithIcons } from '../../../../base/browser/ui/iconLabel/iconLabels.js';
import { Disposable } from '../../../../base/common/lifecycle.js';
import { transaction, constObservable } from '../../../../base/common/observable.js';
import { autorun, autorunWithStore2 } from '../../../../base/common/observableImpl/autorun.js';
import { isDefined } from '../../../../base/common/types.js';
export class UnchangedRangesFeature extends Disposable {
    constructor(_originalEditor, _modifiedEditor, _diffModel) {
        super();
        this._originalEditor = _originalEditor;
        this._modifiedEditor = _modifiedEditor;
        this._diffModel = _diffModel;
        const unchangedRegionViewZoneIdsOrig = [];
        const unchangedRegionViewZoneIdsMod = [];
        this._register(this._originalEditor.onDidChangeCursorPosition(e => {
            const m = this._diffModel.get();
            transaction(tx => {
                for (const s of this._originalEditor.getSelections() || []) {
                    m === null || m === void 0 ? void 0 : m.revealOriginalLine(s.getStartPosition().lineNumber, tx);
                    m === null || m === void 0 ? void 0 : m.revealOriginalLine(s.getEndPosition().lineNumber, tx);
                }
            });
        }));
        this._register(this._modifiedEditor.onDidChangeCursorPosition(e => {
            const m = this._diffModel.get();
            transaction(tx => {
                for (const s of this._modifiedEditor.getSelections() || []) {
                    m === null || m === void 0 ? void 0 : m.revealModifiedLine(s.getStartPosition().lineNumber, tx);
                    m === null || m === void 0 ? void 0 : m.revealModifiedLine(s.getEndPosition().lineNumber, tx);
                }
            });
        }));
        this._register(autorunWithStore2('update folded unchanged regions', (reader, store) => {
            var _a;
            const unchangedRegions = (_a = this._diffModel.read(reader)) === null || _a === void 0 ? void 0 : _a.unchangedRegions.read(reader);
            if (!unchangedRegions) {
                return;
            }
            // TODO@hediet This might cause unnecessary updates of alignment viewzones if this runs too late
            this._originalEditor.changeViewZones((aOrig) => {
                this._modifiedEditor.changeViewZones(aMod => {
                    for (const id of unchangedRegionViewZoneIdsOrig) {
                        aOrig.removeZone(id);
                    }
                    unchangedRegionViewZoneIdsOrig.length = 0;
                    for (const id of unchangedRegionViewZoneIdsMod) {
                        aMod.removeZone(id);
                    }
                    unchangedRegionViewZoneIdsMod.length = 0;
                    for (const r of unchangedRegions) {
                        const atTop = r.modifiedLineNumber !== 1;
                        const atBottom = r.modifiedRange.endLineNumberExclusive !== this._modifiedEditor.getModel().getLineCount() + 1;
                        const hiddenOriginalRange = r.getHiddenOriginalRange(reader);
                        const hiddenModifiedRange = r.getHiddenModifiedRange(reader);
                        if (hiddenOriginalRange.isEmpty) {
                            continue;
                        }
                        store.add(new CollapsedCodeActionsContentWidget(this._originalEditor, aOrig, hiddenOriginalRange.startLineNumber - 1, 30, constObservable([
                            {
                                text: `${hiddenOriginalRange.length} Lines Hidden`
                            },
                            {
                                text: '$(chevron-up) Show More',
                                action() {
                                    return __awaiter(this, void 0, void 0, function* () { r.showMoreAbove(undefined); });
                                },
                            },
                            {
                                text: '$(chevron-down) Show More',
                                action() {
                                    return __awaiter(this, void 0, void 0, function* () { r.showMoreBelow(undefined); });
                                },
                            },
                            {
                                text: '$(close) Show All',
                                action() {
                                    return __awaiter(this, void 0, void 0, function* () { r.showAll(undefined); });
                                },
                            }
                        ]), unchangedRegionViewZoneIdsOrig, atTop, atBottom));
                        store.add(new CollapsedCodeActionsContentWidget(this._modifiedEditor, aMod, hiddenModifiedRange.startLineNumber - 1, 30, constObservable([
                            {
                                text: '$(chevron-up) Show More',
                                action() {
                                    return __awaiter(this, void 0, void 0, function* () { r.showMoreAbove(undefined); });
                                },
                            },
                            {
                                text: '$(chevron-down) Show More',
                                action() {
                                    return __awaiter(this, void 0, void 0, function* () { r.showMoreBelow(undefined); });
                                },
                            },
                            {
                                text: '$(close) Show All',
                                action() {
                                    return __awaiter(this, void 0, void 0, function* () { r.showAll(undefined); });
                                },
                            }
                        ]), unchangedRegionViewZoneIdsMod, atTop, atBottom));
                    }
                });
            });
            this._originalEditor.setHiddenAreas(unchangedRegions.map(r => r.getHiddenOriginalRange(reader).toInclusiveRange()).filter(isDefined));
            this._modifiedEditor.setHiddenAreas(unchangedRegions.map(r => r.getHiddenModifiedRange(reader).toInclusiveRange()).filter(isDefined));
        }));
    }
}
// TODO@hediet avoid code duplication with FixedZoneWidget in merge editor
class FixedZoneWidget extends Disposable {
    constructor(editor, viewZoneAccessor, afterLineNumber, height, viewZoneIdsToCleanUp) {
        super();
        this.editor = editor;
        this.overlayWidgetId = `fixedZoneWidget-${FixedZoneWidget.counter++}`;
        this.widgetDomNode = h('div.fixed-zone-widget').root;
        this.overlayWidget = {
            getId: () => this.overlayWidgetId,
            getDomNode: () => this.widgetDomNode,
            getPosition: () => null
        };
        this.viewZoneId = viewZoneAccessor.addZone({
            domNode: document.createElement('div'),
            afterLineNumber: afterLineNumber,
            heightInPx: height,
            onComputedHeight: (height) => {
                this.widgetDomNode.style.height = `${height}px`;
            },
            onDomNodeTop: (top) => {
                this.widgetDomNode.style.top = `${top}px`;
            },
            showInHiddenAreas: true,
        });
        viewZoneIdsToCleanUp.push(this.viewZoneId);
        this.widgetDomNode.style.left = this.editor.getLayoutInfo().contentLeft + 'px';
        this.editor.addOverlayWidget(this.overlayWidget);
        this._register({
            dispose: () => {
                this.editor.removeOverlayWidget(this.overlayWidget);
            },
        });
    }
}
FixedZoneWidget.counter = 0;
class CollapsedCodeActionsContentWidget extends FixedZoneWidget {
    constructor(editor, viewZoneAccessor, afterLineNumber, height, items, viewZoneIdsToCleanUp, showTopZigZag, showBottomZigZag) {
        super(editor, viewZoneAccessor, afterLineNumber, height, viewZoneIdsToCleanUp);
        this.showTopZigZag = showTopZigZag;
        this.showBottomZigZag = showBottomZigZag;
        this._domNode = h('div.diff-hidden-lines', { className: [this.showTopZigZag ? 'showTop' : '', this.showBottomZigZag ? 'showBottom' : ''].join(' ') }, [
            h('div.top'),
            h('div.center@content'),
            h('div.bottom'),
        ]);
        this.widgetDomNode.appendChild(this._domNode.root);
        this._register(autorun('update commands', (reader) => {
            const i = items.read(reader);
            this.setState(i);
        }));
    }
    setState(items) {
        const children = [];
        let isFirst = true;
        for (const item of items) {
            if (isFirst) {
                isFirst = false;
            }
            else {
                children.push($('span', undefined, '\u00a0|\u00a0'));
            }
            const title = renderLabelWithIcons(item.text);
            if (item.action) {
                children.push($('a', { title: item.tooltip, role: 'button', onclick: () => item.action() }, ...title));
            }
            else {
                children.push($('span', { title: item.tooltip }, ...title));
            }
        }
        reset(this._domNode.content, ...children);
    }
}
