import { __decorate, __param } from '../../../../../../../external/tslib/tslib.es6.js';
import { isRelativePattern } from '../../../../base/common/glob.js';
import { SimpleNotebookProviderInfo, INotebookService } from './notebookService.js';
import { joinPath, isEqual } from '../../../../base/common/resources.js';
import '../../../../../../../override/vs/platform/dialogs/common/dialogs.js';
import { INotebookEditorModelResolverService } from './notebookEditorModelResolverService.js';
import { ILabelService } from '../../../../platform/label/common/label.js';
import { Schemas } from '../../../../base/common/network.js';
import { IFileService } from '../../../../platform/files/common/files.js';
import { AbstractResourceEditorInput } from '../../../common/editor/resourceEditorInput.js';
import { onUnexpectedError } from '../../../../base/common/errors.js';
import { VSBuffer } from '../../../../base/common/buffer.js';
import { IFilesConfigurationService } from '../../../services/filesConfiguration/common/filesConfigurationService.js';
import { IExtensionService } from '../../../services/extensions/common/extensions.js';
import { localizeWithPath } from '../../../../nls.js';
import { IEditorService } from '../../../services/editor/common/editorService.js';
import { ITextResourceConfigurationService } from '../../../../editor/common/services/textResourceConfiguration.js';
import { ICustomEditorLabelService } from '../../../services/editor/common/customEditorLabelService.js';
import { IFileDialogService } from '../../../../platform/dialogs/common/dialogs.js';
var NotebookEditorInput_1;
let NotebookEditorInput = class NotebookEditorInput extends AbstractResourceEditorInput {
    static { NotebookEditorInput_1 = this; }
    static getOrCreate(instantiationService, resource, preferredResource, viewType, options = {}) {
        const editor = instantiationService.createInstance(NotebookEditorInput_1, resource, preferredResource, viewType, options);
        if (preferredResource) {
            editor.setPreferredResource(preferredResource);
        }
        return editor;
    }
    static { this.ID = 'workbench.input.notebook'; }
    constructor(resource, preferredResource, viewType, options, _notebookService, _notebookModelResolverService, _fileDialogService, labelService, fileService, filesConfigurationService, extensionService, editorService, textResourceConfigurationService, customEditorLabelService) {
        super(resource, preferredResource, labelService, fileService, filesConfigurationService, textResourceConfigurationService, customEditorLabelService);
        this.viewType = viewType;
        this.options = options;
        this._notebookService = _notebookService;
        this._notebookModelResolverService = _notebookModelResolverService;
        this._fileDialogService = _fileDialogService;
        this._editorModelReference = null;
        this._defaultDirtyState = false;
        this._defaultDirtyState = !!options.startDirty;
        this._sideLoadedListener = _notebookService.onDidAddNotebookDocument(e => {
            if (e.viewType === this.viewType && ( e.uri.toString()) === ( this.resource.toString())) {
                this.resolve().catch(onUnexpectedError);
            }
        });
        this._register(extensionService.onWillStop(e => {
            if (!this.isDirty()) {
                return;
            }
            e.veto((async () => {
                const editors = editorService.findEditors(this);
                if (editors.length > 0) {
                    const result = await editorService.save(editors[0]);
                    if (result.success) {
                        return false;
                    }
                }
                return true;
            })(), ( localizeWithPath(
                'vs/workbench/contrib/notebook/common/notebookEditorInput',
                'vetoExtHostRestart',
                "Notebook '{0}' could not be saved.",
                this.resource.path
            )));
        }));
    }
    dispose() {
        this._sideLoadedListener.dispose();
        this._editorModelReference?.dispose();
        this._editorModelReference = null;
        super.dispose();
    }
    get typeId() {
        return NotebookEditorInput_1.ID;
    }
    get editorId() {
        return this.viewType;
    }
    get capabilities() {
        let capabilities = 0 ;
        if (this.resource.scheme === Schemas.untitled) {
            capabilities |= 4 ;
        }
        if (this._editorModelReference) {
            if (this._editorModelReference.object.isReadonly()) {
                capabilities |= 2 ;
            }
        }
        else {
            if (this.filesConfigurationService.isReadonly(this.resource)) {
                capabilities |= 2 ;
            }
        }
        if (!((capabilities & 2) )) {
            capabilities |= 128 ;
        }
        return capabilities;
    }
    getDescription(verbosity = 1 ) {
        if (!this.hasCapability(4 ) || this._editorModelReference?.object.hasAssociatedFilePath()) {
            return super.getDescription(verbosity);
        }
        return undefined;
    }
    isReadonly() {
        if (!this._editorModelReference) {
            return this.filesConfigurationService.isReadonly(this.resource);
        }
        return this._editorModelReference.object.isReadonly();
    }
    isDirty() {
        if (!this._editorModelReference) {
            return this._defaultDirtyState;
        }
        return this._editorModelReference.object.isDirty();
    }
    isSaving() {
        const model = this._editorModelReference?.object;
        if (!model || !model.isDirty() || model.hasErrorState || this.hasCapability(4 )) {
            return false;
        }
        return this.filesConfigurationService.hasShortAutoSaveDelay(this);
    }
    async save(group, options) {
        if (this._editorModelReference) {
            if (this.hasCapability(4 )) {
                return this.saveAs(group, options);
            }
            else {
                await this._editorModelReference.object.save(options);
            }
            return this;
        }
        return undefined;
    }
    async saveAs(group, options) {
        if (!this._editorModelReference) {
            return undefined;
        }
        const provider = this._notebookService.getContributedNotebookType(this.viewType);
        if (!provider) {
            return undefined;
        }
        const pathCandidate = this.hasCapability(4 ) ? await this._suggestName(provider, this.labelService.getUriBasenameLabel(this.resource)) : this._editorModelReference.object.resource;
        let target;
        if (this._editorModelReference.object.hasAssociatedFilePath()) {
            target = pathCandidate;
        }
        else {
            target = await this._fileDialogService.pickFileToSave(pathCandidate, options?.availableFileSystems);
            if (!target) {
                return undefined;
            }
        }
        if (!provider.matches(target)) {
            const patterns = ( provider.selectors.map(pattern => {
                if (typeof pattern === 'string') {
                    return pattern;
                }
                if (isRelativePattern(pattern)) {
                    return `${pattern} (base ${pattern.base})`;
                }
                if (pattern.exclude) {
                    return `${pattern.include} (exclude: ${pattern.exclude})`;
                }
                else {
                    return `${pattern.include}`;
                }
            })).join(', ');
            throw new Error(`File name ${target} is not supported by ${provider.providerDisplayName}.\n\nPlease make sure the file name matches following patterns:\n${patterns}`);
        }
        return await this._editorModelReference.object.saveAs(target);
    }
    async _suggestName(provider, suggestedFilename) {
        const firstSelector = provider.selectors[0];
        let selectorStr = firstSelector && typeof firstSelector === 'string' ? firstSelector : undefined;
        if (!selectorStr && firstSelector) {
            const include = firstSelector.include;
            if (typeof include === 'string') {
                selectorStr = include;
            }
        }
        if (selectorStr) {
            const matches = /^\*\.([A-Za-z_-]*)$/.exec(selectorStr);
            if (matches && matches.length > 1) {
                const fileExt = matches[1];
                if (!suggestedFilename.endsWith(fileExt)) {
                    return joinPath(await this._fileDialogService.defaultFilePath(), suggestedFilename + '.' + fileExt);
                }
            }
        }
        return joinPath(await this._fileDialogService.defaultFilePath(), suggestedFilename);
    }
    async rename(group, target) {
        if (this._editorModelReference) {
            return { editor: { resource: target }, options: { override: this.viewType } };
        }
        return undefined;
    }
    async revert(_group, options) {
        if (this._editorModelReference && this._editorModelReference.object.isDirty()) {
            await this._editorModelReference.object.revert(options);
        }
    }
    async resolve(_options, perf) {
        if (!(await this._notebookService.canResolve(this.viewType))) {
            return null;
        }
        perf?.mark('extensionActivated');
        this._sideLoadedListener.dispose();
        if (!this._editorModelReference) {
            const ref = await this._notebookModelResolverService.resolve(this.resource, this.viewType, this.ensureLimits(_options));
            if (this._editorModelReference) {
                ref.dispose();
                return this._editorModelReference.object;
            }
            this._editorModelReference = ref;
            if (this.isDisposed()) {
                this._editorModelReference.dispose();
                this._editorModelReference = null;
                return null;
            }
            this._register(this._editorModelReference.object.onDidChangeDirty(() => this._onDidChangeDirty.fire()));
            this._register(this._editorModelReference.object.onDidChangeReadonly(() => this._onDidChangeCapabilities.fire()));
            this._register(this._editorModelReference.object.onDidRevertUntitled(() => this.dispose()));
            if (this._editorModelReference.object.isDirty()) {
                this._onDidChangeDirty.fire();
            }
        }
        else {
            this._editorModelReference.object.load({ limits: this.ensureLimits(_options) });
        }
        if (this.options._backupId) {
            const info = await this._notebookService.withNotebookDataProvider(this._editorModelReference.object.notebook.viewType);
            if (!(info instanceof SimpleNotebookProviderInfo)) {
                throw new Error('CANNOT open file notebook with this provider');
            }
            const data = await info.serializer.dataToNotebook(VSBuffer.fromString(JSON.stringify({ __webview_backup: this.options._backupId })));
            this._editorModelReference.object.notebook.applyEdits([
                {
                    editType: 1 ,
                    index: 0,
                    count: this._editorModelReference.object.notebook.length,
                    cells: data.cells
                }
            ], true, undefined, () => undefined, undefined, false);
            if (this.options._workingCopy) {
                this.options._backupId = undefined;
                this.options._workingCopy = undefined;
                this.options.startDirty = undefined;
            }
        }
        return this._editorModelReference.object;
    }
    toUntyped() {
        return {
            resource: this.resource,
            options: {
                override: this.viewType
            }
        };
    }
    matches(otherInput) {
        if (super.matches(otherInput)) {
            return true;
        }
        if (otherInput instanceof NotebookEditorInput_1) {
            return this.viewType === otherInput.viewType && isEqual(this.resource, otherInput.resource);
        }
        return false;
    }
};
NotebookEditorInput = NotebookEditorInput_1 = ( __decorate([
    ( __param(4, INotebookService)),
    ( __param(5, INotebookEditorModelResolverService)),
    ( __param(6, IFileDialogService)),
    ( __param(7, ILabelService)),
    ( __param(8, IFileService)),
    ( __param(9, IFilesConfigurationService)),
    ( __param(10, IExtensionService)),
    ( __param(11, IEditorService)),
    ( __param(12, ITextResourceConfigurationService)),
    ( __param(13, ICustomEditorLabelService))
], NotebookEditorInput));
function isCompositeNotebookEditorInput(thing) {
    return !!thing
        && typeof thing === 'object'
        && Array.isArray(thing.editorInputs)
        && (thing.editorInputs.every(input => input instanceof NotebookEditorInput));
}
function isNotebookEditorInput(thing) {
    return !!thing
        && typeof thing === 'object'
        && thing instanceof NotebookEditorInput;
}
export { NotebookEditorInput, isCompositeNotebookEditorInput, isNotebookEditorInput };
