"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ExtHostFileSystemEvent = void 0;
const tslib_1 = require("tslib");
const ide_core_common_1 = require("@opensumi/ide-core-common");
const vscode_1 = require("../../../common/vscode");
const TypeConverts = tslib_1.__importStar(require("../../../common/vscode/converter"));
const ext_types_1 = require("../../../common/vscode/ext-types");
class FileSystemWatcher {
    get ignoreCreateEvents() {
        return Boolean(this._config & 0b001);
    }
    get ignoreChangeEvents() {
        return Boolean(this._config & 0b010);
    }
    get ignoreDeleteEvents() {
        return Boolean(this._config & 0b100);
    }
    constructor(dispatcher, globPattern, ignoreCreateEvents, ignoreChangeEvents, ignoreDeleteEvents) {
        this._onDidCreate = new ide_core_common_1.Emitter();
        this._onDidChange = new ide_core_common_1.Emitter();
        this._onDidDelete = new ide_core_common_1.Emitter();
        this._config = 0;
        if (ignoreCreateEvents) {
            this._config += 0b001;
        }
        if (ignoreChangeEvents) {
            this._config += 0b010;
        }
        if (ignoreDeleteEvents) {
            this._config += 0b100;
        }
        const parsedPattern = (0, ide_core_common_1.parseGlob)(globPattern);
        const subscription = dispatcher((events) => {
            if (!ignoreCreateEvents) {
                for (const created of events.created) {
                    const uri = ide_core_common_1.URI.revive(created);
                    if (parsedPattern(uri.fsPath)) {
                        this._onDidCreate.fire(uri);
                    }
                }
            }
            if (!ignoreChangeEvents) {
                for (const changed of events.changed) {
                    const uri = ide_core_common_1.URI.revive(changed);
                    if (parsedPattern(uri.fsPath)) {
                        this._onDidChange.fire(uri);
                    }
                }
            }
            if (!ignoreDeleteEvents) {
                for (const deleted of events.deleted) {
                    const uri = ide_core_common_1.URI.revive(deleted);
                    if (parsedPattern(uri.fsPath)) {
                        this._onDidDelete.fire(uri);
                    }
                }
            }
        });
        this._disposable = new ide_core_common_1.Disposable(this._onDidCreate, this._onDidChange, this._onDidDelete, subscription);
    }
    dispose() {
        this._disposable.dispose();
    }
    get onDidCreate() {
        return this._onDidCreate.event;
    }
    get onDidChange() {
        return this._onDidChange.event;
    }
    get onDidDelete() {
        return this._onDidDelete.event;
    }
}
class ExtHostFileSystemEvent {
    constructor(rpcProtocol, _extHostDocumentsAndEditors) {
        this.rpcProtocol = rpcProtocol;
        this._extHostDocumentsAndEditors = _extHostDocumentsAndEditors;
        this._onFileSystemEvent = new ide_core_common_1.Emitter();
        this._onDidRenameFile = new ide_core_common_1.Emitter();
        this._onDidCreateFile = new ide_core_common_1.Emitter();
        this._onDidDeleteFile = new ide_core_common_1.Emitter();
        this._onWillRenameFile = new ide_core_common_1.AsyncEmitter();
        this._onWillCreateFile = new ide_core_common_1.AsyncEmitter();
        this._onWillDeleteFile = new ide_core_common_1.AsyncEmitter();
        this.onDidRenameFile = this._onDidRenameFile.event;
        this.onDidCreateFile = this._onDidCreateFile.event;
        this.onDidDeleteFile = this._onDidDeleteFile.event;
        this.logger = (0, ide_core_common_1.getDebugLogger)();
        this._proxy = this.rpcProtocol.getProxy(vscode_1.MainThreadAPIIdentifier.MainThreadWorkspace);
    }
    // --- file events
    createFileSystemWatcher(globPattern, ignoreCreateEvents, ignoreChangeEvents, ignoreDeleteEvents) {
        return new FileSystemWatcher(this._onFileSystemEvent.event, globPattern, ignoreCreateEvents, ignoreChangeEvents, ignoreDeleteEvents);
    }
    $onFileEvent(events) {
        this._onFileSystemEvent.fire(events);
    }
    // --- file operations
    $onDidRunFileOperation(operation, files) {
        switch (operation) {
            case 2 /* FileOperation.MOVE */:
                this._onDidRenameFile.fire(Object.freeze({ files: files.map((f) => ({ oldUri: ide_core_common_1.URI.revive(f.source), newUri: ide_core_common_1.URI.revive(f.target) })) }));
                break;
            case 1 /* FileOperation.DELETE */:
                this._onDidDeleteFile.fire(Object.freeze({ files: files.map((f) => ide_core_common_1.URI.revive(f.target)) }));
                break;
            case 0 /* FileOperation.CREATE */:
                this._onDidCreateFile.fire(Object.freeze({ files: files.map((f) => ide_core_common_1.URI.revive(f.target)) }));
                break;
            default:
            // ignore, dont send
        }
    }
    getOnWillRenameFileEvent(extension) {
        return this._createWillExecuteEvent(extension, this._onWillRenameFile);
    }
    getOnWillCreateFileEvent(extension) {
        return this._createWillExecuteEvent(extension, this._onWillCreateFile);
    }
    getOnWillDeleteFileEvent(extension) {
        return this._createWillExecuteEvent(extension, this._onWillDeleteFile);
    }
    _createWillExecuteEvent(extension, emitter) {
        return (listener, thisArg, disposables) => {
            const wrappedListener = function wrapped(e) {
                listener.call(thisArg, e);
            };
            wrappedListener.extension = extension;
            return emitter.event(wrappedListener, undefined, disposables);
        };
    }
    async $onWillRunFileOperation(operation, files, timeout, token) {
        switch (operation) {
            case 2 /* FileOperation.MOVE */:
                return await this._fireWillEvent(this._onWillRenameFile, {
                    files: files.map((f) => ({ oldUri: ide_core_common_1.URI.revive(f.source), newUri: ide_core_common_1.URI.revive(f.target) })),
                    token,
                }, timeout, token);
            case 1 /* FileOperation.DELETE */:
                return await this._fireWillEvent(this._onWillDeleteFile, { files: files.map((f) => ide_core_common_1.URI.revive(f.target)), token }, timeout, token);
            case 0 /* FileOperation.CREATE */:
                return await this._fireWillEvent(this._onWillCreateFile, { files: files.map((f) => ide_core_common_1.URI.revive(f.target)), token }, timeout, token);
            default:
                return undefined;
        }
    }
    async _fireWillEvent(emitter, data, timeout, token) {
        const extensionNames = new Set();
        const edits = [];
        await emitter.fireAsync(data, token, async (thenable, listener) => {
            var _a, _b;
            // ignore all results except for WorkspaceEdits. Those are stored in an array.
            const now = Date.now();
            const result = await Promise.resolve(thenable);
            if (result instanceof ext_types_1.WorkspaceEdit) {
                edits.push(result);
                extensionNames.add((_a = listener.extension.displayName) !== null && _a !== void 0 ? _a : listener.extension.identifier.value);
            }
            if (Date.now() - now > timeout) {
                this.logger.log('SLOW file-participant', (_b = listener.extension) === null || _b === void 0 ? void 0 : _b.id);
            }
        });
        if (token.isCancellationRequested) {
            return undefined;
        }
        if (edits.length === 0) {
            return undefined;
        }
        if (edits.length > 0) {
            // concat all WorkspaceEdits collected via waitUntil-call and apply them in one go.
            const dto = { edits: [] };
            for (const edit of edits) {
                const { edits } = TypeConverts.WorkspaceEdit.from(edit, this._extHostDocumentsAndEditors);
                dto.edits = dto.edits.concat(edits);
            }
            return {
                edit: dto,
                extensionNames: Array.from(extensionNames),
            };
            // return this._proxy.$tryApplyWorkspaceEdit(dto);
        }
    }
}
exports.ExtHostFileSystemEvent = ExtHostFileSystemEvent;
//# sourceMappingURL=ext.host.file-system-event.js.map