"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MainThreadFileSystemEvent = void 0;
const tslib_1 = require("tslib");
const di_1 = require("@opensumi/di");
const ide_connection_1 = require("@opensumi/ide-connection");
const ide_core_browser_1 = require("@opensumi/ide-core-browser");
const progress_1 = require("@opensumi/ide-core-browser/lib/progress");
const ide_core_common_1 = require("@opensumi/ide-core-common");
const ide_file_service_1 = require("@opensumi/ide-file-service");
const monaco_api_1 = require("@opensumi/ide-monaco/lib/browser/monaco-api");
const ide_overlay_1 = require("@opensumi/ide-overlay");
const ide_workspace_edit_1 = require("@opensumi/ide-workspace-edit");
const vscode_1 = require("../../../common/vscode");
let MainThreadFileSystemEvent = class MainThreadFileSystemEvent extends ide_core_common_1.Disposable {
    constructor(rpcProtocol) {
        super();
        this.rpcProtocol = rpcProtocol;
        this._proxy = this.rpcProtocol.getProxy(vscode_1.ExtHostAPIIdentifier.ExtHostFileSystemEvent);
        // dispatch file event to ext-host
        this._dispatchFileEventListener();
        // do somethings when file operation is happening
        this._participateFileOperation();
        // Init listener for showPreview
        this._initShowPreview();
    }
    _dispatchFileEventListener() {
        // file system events - (changes the editor and other make)
        const events = {
            created: [],
            changed: [],
            deleted: [],
        };
        this.addDispose(this.fileService.onFilesChanged((changes) => {
            let hasResult = false;
            for (const change of changes) {
                switch (change.type) {
                    case ide_file_service_1.FileChangeType.ADDED:
                        events.created.push(ide_core_common_1.Uri.parse(change.uri));
                        hasResult = true;
                        break;
                    case ide_file_service_1.FileChangeType.UPDATED:
                        events.changed.push(ide_core_common_1.Uri.parse(change.uri));
                        hasResult = true;
                        break;
                    case ide_file_service_1.FileChangeType.DELETED:
                        events.deleted.push(ide_core_common_1.Uri.parse(change.uri));
                        hasResult = true;
                        break;
                }
            }
            if (hasResult) {
                this._proxy.$onFileEvent(events);
                events.created = [];
                events.changed = [];
                events.deleted = [];
            }
        }));
    }
    _participateFileOperation() {
        // BEFORE file operation
        this.addDispose(this.workspaceFileService.registerFileOperationParticipant({
            participate: this.fileOperationParticipant.bind(this),
        }));
        // AFTER file operation
        this.addDispose(this.workspaceFileService.onDidRunWorkspaceFileOperation((e) => this._proxy.$onDidRunFileOperation(e.operation, e.files)));
    }
    _initShowPreview() {
        // additional edits for file-participants
        this._showPreview = this.preferenceService.get('workbench.refactoringChanges.showPreviewStrategy');
        this.addDispose(this.preferenceService.onPreferenceChanged((e) => {
            if (e.preferenceName === 'workbench.refactoringChanges.showPreviewStrategy') {
                this._showPreview = e.newValue;
            }
        }));
    }
    async fileOperationParticipant(...args) {
        const [files, operation, _, timeout, token] = args;
        const cts = new ide_core_common_1.CancellationTokenSource(token);
        const timer = setTimeout(() => cts.cancel(), timeout);
        const data = await this.progressService
            .withProgress({
            location: ide_core_common_1.ProgressLocation.Notification,
            title: this.getProgressLabel(operation),
            cancellable: true,
            delay: Math.min(timeout / 2, 3000),
        }, () => {
            // race ext-host event response against timeout/cancellation
            const onWillEvent = this._proxy.$onWillRunFileOperation(operation, files, timeout, token);
            return (0, ide_core_common_1.raceCancellation)(onWillEvent, cts.token);
        }, () => {
            // user-cancel
            cts.cancel();
        })
            .finally(() => {
            cts.dispose();
            clearTimeout(timer);
        });
        if (!data) {
            // cancelled or no reply
            return;
        }
        let showPreview = this._showPreview;
        const needsConfirmation = data.edit.edits.some((edit) => { var _a; return (_a = edit.metadata) === null || _a === void 0 ? void 0 : _a.needsConfirmation; });
        if (showPreview === 'askMe') {
            // Interaction with user
            let message;
            if (data.extensionNames.length === 1) {
                if (operation === 0 /* FileOperation.CREATE */) {
                    message = (0, ide_core_common_1.formatLocalize)('refactoring-changes.ask.1.create', data.extensionNames[0]);
                }
                else if (operation === 3 /* FileOperation.COPY */) {
                    message = (0, ide_core_common_1.formatLocalize)('refactoring-changes.ask.1.copy', data.extensionNames[0]);
                }
                else if (operation === 2 /* FileOperation.MOVE */) {
                    message = (0, ide_core_common_1.formatLocalize)('refactoring-changes.ask.1.move', data.extensionNames[0]);
                } /* if (operation === FileOperation.DELETE) */
                else {
                    message = (0, ide_core_common_1.formatLocalize)('refactoring-changes.ask.1.delete', data.extensionNames[0]);
                }
            }
            else {
                if (operation === 0 /* FileOperation.CREATE */) {
                    message = (0, ide_core_common_1.formatLocalize)('refactoring-changes.ask.N.create', data.extensionNames.length);
                }
                else if (operation === 3 /* FileOperation.COPY */) {
                    message = (0, ide_core_common_1.formatLocalize)('refactoring-changes.ask.N.copy', data.extensionNames.length);
                }
                else if (operation === 2 /* FileOperation.MOVE */) {
                    message = (0, ide_core_common_1.formatLocalize)('refactoring-changes.ask.N.move', data.extensionNames.length);
                } /* if (operation === FileOperation.DELETE) */
                else {
                    message = (0, ide_core_common_1.formatLocalize)('refactoring-changes.ask.N.delete', data.extensionNames.length);
                }
            }
            if (needsConfirmation) {
                const choices = [
                    (0, ide_core_common_1.localize)('refactoring-changes.msg.showPreview'),
                    (0, ide_core_common_1.localize)('refactoring-changes.msg.skipChanges'),
                ];
                // edit#metadata.needsConfirmation#true --> show dialog
                const answer = await this.dialogService.open({ message, type: ide_core_common_1.MessageType.Info, buttons: choices });
                showPreview = 'show';
                if (answer === choices[1]) {
                    // Skip changes
                    return;
                }
            }
            else {
                const choices = [
                    (0, ide_core_common_1.localize)('refactoring-changes.msg.showPreview'),
                    (0, ide_core_common_1.localize)('refactoring-changes.msg.skipChanges'),
                    (0, ide_core_common_1.localize)('component.modal.okText'),
                ];
                const answer = await this.dialogService.open({ message, type: ide_core_common_1.MessageType.Info, buttons: choices });
                if (answer === choices[1]) {
                    // Skip changes
                    return;
                }
                showPreview = answer === choices[0] ? 'show' : 'hide';
            }
        }
        this.logger.log('[onWill-handler] applying additional workspace edit from extensions', data.extensionNames);
        const workspaceEditDto = data === null || data === void 0 ? void 0 : data.edit;
        if (workspaceEditDto) {
            await this.bulkEditService.apply(monaco_api_1.ResourceEdit.convert(workspaceEditDto), { showPreview: showPreview === 'show' });
        }
    }
    getProgressLabel(operation) {
        switch (operation) {
            case 0 /* FileOperation.CREATE */:
                return (0, ide_core_common_1.localize)('fileOperation.create', "Running 'File Create' participants...");
            case 1 /* FileOperation.DELETE */:
                return (0, ide_core_common_1.localize)('fileOperation.delete', "Running 'File Delete' participants...");
            case 3 /* FileOperation.COPY */:
                return (0, ide_core_common_1.localize)('fileOperation.copy', "Running 'File Copy' participants...");
            case 2 /* FileOperation.MOVE */:
                return (0, ide_core_common_1.localize)('fileOperation.move', "Running 'File Move' participants...");
        }
    }
};
exports.MainThreadFileSystemEvent = MainThreadFileSystemEvent;
tslib_1.__decorate([
    (0, di_1.Autowired)(ide_file_service_1.IFileServiceClient),
    tslib_1.__metadata("design:type", Object)
], MainThreadFileSystemEvent.prototype, "fileService", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(ide_workspace_edit_1.IWorkspaceFileService),
    tslib_1.__metadata("design:type", Object)
], MainThreadFileSystemEvent.prototype, "workspaceFileService", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(ide_core_browser_1.PreferenceService),
    tslib_1.__metadata("design:type", Object)
], MainThreadFileSystemEvent.prototype, "preferenceService", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(progress_1.IProgressService),
    tslib_1.__metadata("design:type", Object)
], MainThreadFileSystemEvent.prototype, "progressService", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(ide_core_common_1.ILogger),
    tslib_1.__metadata("design:type", Object)
], MainThreadFileSystemEvent.prototype, "logger", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(ide_overlay_1.IDialogService),
    tslib_1.__metadata("design:type", Object)
], MainThreadFileSystemEvent.prototype, "dialogService", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(ide_workspace_edit_1.IBulkEditServiceShape),
    tslib_1.__metadata("design:type", Object)
], MainThreadFileSystemEvent.prototype, "bulkEditService", void 0);
exports.MainThreadFileSystemEvent = MainThreadFileSystemEvent = tslib_1.__decorate([
    (0, di_1.Injectable)({ multiple: true }),
    tslib_1.__metadata("design:paramtypes", [Object])
], MainThreadFileSystemEvent);
//# sourceMappingURL=main.thread.file-system-event.js.map