import { __decorate, __param } from '../../../../../../../external/tslib/tslib.es6.js';
import { Disposable } from '../../../../base/common/lifecycle.js';
import { observableValue } from '../../../../base/common/observableInternal/base.js';
import { derived, derivedDisposable, derivedWithSetter } from '../../../../base/common/observableInternal/derived.js';
import '../../../../base/common/observableInternal/autorun.js';
import { derivedObservableWithCache } from '../../../../base/common/observableInternal/utils.js';
import '../../../../base/common/cancellation.js';
import '../../../../base/common/arrays.js';
import { observableCodeEditor } from '../../../browser/observableCodeEditor.js';
import { readHotReloadableExport } from '../../../browser/widget/diffEditor/utils.js';
import { Selection } from '../../../common/core/selection.js';
import { ILanguageFeatureDebounceService } from '../../../common/services/languageFeatureDebounce.js';
import { ILanguageFeaturesService } from '../../../common/services/languageFeatures.js';
import { inlineEditVisible, isPinnedContextKey } from './consts.js';
import { InlineEditsModel } from './inlineEditsModel.js';
import { InlineEditsWidget } from './inlineEditsWidget.js';
import { IConfigurationService } from '../../../../platform/configuration/common/configuration.service.js';
import { IContextKeyService } from '../../../../platform/contextkey/common/contextkey.service.js';
import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js';
import { observableConfigValue, bindContextKey } from '../../../../platform/observable/common/platformObservableUtils.js';
var InlineEditsController_1;
let InlineEditsController = class InlineEditsController extends Disposable {
    static { InlineEditsController_1 = this; }
    static { this.ID = 'editor.contrib.inlineEditsController'; }
    static get(editor) {
        return editor.getContribution(InlineEditsController_1.ID);
    }
    constructor(editor, _instantiationService, _contextKeyService, _debounceService, _languageFeaturesService, _configurationService) {
        super();
        this.editor = editor;
        this._instantiationService = _instantiationService;
        this._contextKeyService = _contextKeyService;
        this._debounceService = _debounceService;
        this._languageFeaturesService = _languageFeaturesService;
        this._configurationService = _configurationService;
        this._enabled = observableConfigValue('editor.inlineEdits.enabled', false, this._configurationService);
        this._editorObs = observableCodeEditor(this.editor);
        this._selection = derived(this, reader => this._editorObs.cursorSelection.read(reader) ?? ( new Selection(1, 1, 1, 1)));
        this._debounceValue = this._debounceService.for(this._languageFeaturesService.inlineCompletionsProvider, 'InlineEditsDebounce', { min: 50, max: 50 });
        this.model = derivedDisposable(this, reader => {
            if (!this._enabled.read(reader)) {
                return undefined;
            }
            if (this._editorObs.isReadonly.read(reader)) {
                return undefined;
            }
            const textModel = this._editorObs.model.read(reader);
            if (!textModel) {
                return undefined;
            }
            const model = this._instantiationService.createInstance(readHotReloadableExport(InlineEditsModel, reader), textModel, this._editorObs.versionId, this._selection, this._debounceValue);
            return model;
        });
        this._hadInlineEdit = derivedObservableWithCache(this, (reader, lastValue) => lastValue || this.model.read(reader)?.inlineEdit.read(reader) !== undefined);
        this._widget = derivedDisposable(this, reader => {
            if (!this._hadInlineEdit.read(reader)) {
                return undefined;
            }
            return this._instantiationService.createInstance(readHotReloadableExport(InlineEditsWidget, reader), this.editor, ( this.model.map((m, reader) => m?.inlineEdit.read(reader))), flattenSettableObservable((reader) => this.model.read(reader)?.userPrompt ?? observableValue('empty', '')));
        });
        this._register(bindContextKey(inlineEditVisible, this._contextKeyService, r => !!this.model.read(r)?.inlineEdit.read(r)));
        this._register(bindContextKey(isPinnedContextKey, this._contextKeyService, r => !!this.model.read(r)?.isPinned.read(r)));
        this.model.recomputeInitiallyAndOnChange(this._store);
        this._widget.recomputeInitiallyAndOnChange(this._store);
    }
};
InlineEditsController = InlineEditsController_1 = ( __decorate([
    ( __param(1, IInstantiationService)),
    ( __param(2, IContextKeyService)),
    ( __param(3, ILanguageFeatureDebounceService)),
    ( __param(4, ILanguageFeaturesService)),
    ( __param(5, IConfigurationService))
], InlineEditsController));
function flattenSettableObservable(fn) {
    return derivedWithSetter(undefined, reader => {
        const obs = fn(reader);
        return obs.read(reader);
    }, (value, tx) => {
        fn(undefined).set(value, tx);
    });
}
export { InlineEditsController };
