
import { __decorate, __param } from '../../../../../../../external/tslib/tslib.es6.js';
import { Disposable, toDisposable, DisposableStore } from '../../../../base/common/lifecycle.js';
import '../../../../base/common/observableInternal/index.js';
import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js';
import { IModelService } from '../../../common/services/model.service.js';
import { DiffEditorOptions } from '../diffEditor/diffEditorOptions.js';
import { DiffEditorViewModel } from '../diffEditor/diffEditorViewModel.js';
import { RefCounted } from '../diffEditor/utils.js';
import { observableFromValueWithChangeEvent } from '../../../../base/common/observableInternal/utils/valueWithChangeEvent.js';
import { mapObservableArrayCached, derivedObservableWithWritableCache } from '../../../../base/common/observableInternal/utils/utils.js';
import { transaction } from '../../../../base/common/observableInternal/transaction.js';
import { derived } from '../../../../base/common/observableInternal/observables/derived.js';
import { observableValue } from '../../../../base/common/observableInternal/observables/observableValue.js';
import { constObservable } from '../../../../base/common/observableInternal/observables/constObservable.js';

class MultiDiffEditorViewModel extends Disposable {
    async waitForDiffs() {
        for (const d of this.items.get()) {
            await d.diffEditorViewModel.waitForDiff();
        }
    }
    collapseAll() {
        transaction(tx => {
            for (const d of this.items.get()) {
                d.collapsed.set(true, tx);
            }
        });
    }
    expandAll() {
        transaction(tx => {
            for (const d of this.items.get()) {
                d.collapsed.set(false, tx);
            }
        });
    }
    get contextKeys() {
        return this.model.contextKeys;
    }
    constructor(model, _instantiationService) {
        super();
        this.model = model;
        this._instantiationService = _instantiationService;
        this._documents = observableFromValueWithChangeEvent(this.model, this.model.documents);
        this._documentsArr = derived(this, reader => {
            const result = this._documents.read(reader);
            if (result === "loading") {
                return [];
            }
            return result;
        });
        this.isLoading = derived(this, reader => this._documents.read(reader) === "loading");
        this.items = mapObservableArrayCached(this, this._documentsArr, (d, store) => store.add(
            this._instantiationService.createInstance(DocumentDiffItemViewModel, d, this)
        )).recomputeInitiallyAndOnChange(this._store);
        this.focusedDiffItem = derived(
            this,
            reader => this.items.read(reader).find(i => i.isFocused.read(reader))
        );
        this.activeDiffItem = derivedObservableWithWritableCache(
            this,
            (reader, lastValue) => this.focusedDiffItem.read(reader) ?? (lastValue && this.items.read(reader).indexOf(lastValue) !== -1) ? lastValue : undefined
        );
    }
}
let DocumentDiffItemViewModel = class DocumentDiffItemViewModel extends Disposable {
    get diffEditorViewModel() {
        return this.diffEditorViewModelRef.object;
    }
    get originalUri() {
        return this.documentDiffItem.original?.uri;
    }
    get modifiedUri() {
        return this.documentDiffItem.modified?.uri;
    }
    setIsFocused(source, tx) {
        this._isFocusedSource.set(source, tx);
    }
    get documentDiffItem() {
        return this.documentDiffItemRef.object;
    }
    constructor(documentDiffItem, _editorViewModel, _instantiationService, _modelService) {
        super();
        this._editorViewModel = _editorViewModel;
        this._instantiationService = _instantiationService;
        this._modelService = _modelService;
        this.collapsed = observableValue(this, false);
        this.lastTemplateData = observableValue(this, {
            contentHeight: 500,
            selections: undefined
        });
        this.isActive = derived(this, reader => this._editorViewModel.activeDiffItem.read(reader) === this);
        this._isFocusedSource = observableValue(this, constObservable(false));
        this.isFocused = derived(this, reader => this._isFocusedSource.read(reader).read(reader));
        this.isAlive = observableValue(this, true);
        this._register(toDisposable(() => {
            this.isAlive.set(false, undefined);
        }));
        this.documentDiffItemRef = this._register(documentDiffItem.createNewRef(this));
        function updateOptions(options) {
            return {
                ...options,
                hideUnchangedRegions: {
                    enabled: true
                }
            };
        }
        const options = this._instantiationService.createInstance(DiffEditorOptions, updateOptions(this.documentDiffItem.options || {}));
        if (this.documentDiffItem.onOptionsDidChange) {
            this._register(this.documentDiffItem.onOptionsDidChange(() => {
                options.updateOptions(updateOptions(this.documentDiffItem.options || {}));
            }));
        }
        const diffEditorViewModelStore = ( new DisposableStore());
        const originalTextModel = this.documentDiffItem.original ?? diffEditorViewModelStore.add(this._modelService.createModel("", null));
        const modifiedTextModel = this.documentDiffItem.modified ?? diffEditorViewModelStore.add(this._modelService.createModel("", null));
        diffEditorViewModelStore.add(this.documentDiffItemRef.createNewRef(this));
        this.diffEditorViewModelRef = this._register(
            RefCounted.createWithDisposable(this._instantiationService.createInstance(DiffEditorViewModel, {
                original: originalTextModel,
                modified: modifiedTextModel
            }, options), diffEditorViewModelStore, this)
        );
    }
    getKey() {
        return JSON.stringify([this.originalUri?.toString(), this.modifiedUri?.toString()]);
    }
};
DocumentDiffItemViewModel = ( __decorate([( __param(2, IInstantiationService)), ( __param(3, IModelService))], DocumentDiffItemViewModel));

export { DocumentDiffItemViewModel, MultiDiffEditorViewModel };
