"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ExtHostDecorations = void 0;
const ide_core_common_1 = require("@opensumi/ide-core-common");
const vscode_1 = require("../../../common/vscode");
const ext_types_1 = require("../../../common/vscode/ext-types");
const { asArray, groupBy } = ide_core_common_1.arrays;
const { compare, count } = ide_core_common_1.strings;
const { dirname } = ide_core_common_1.path;
function isFileDecorationProvider(provider) {
    return !!provider.onDidChangeFileDecorations || !!provider.provideFileDecoration;
}
class ExtHostDecorations {
    constructor(rpcProtocol) {
        this.logger = (0, ide_core_common_1.getDebugLogger)();
        this._provider = new Map();
        this.proxy = rpcProtocol.getProxy(vscode_1.MainThreadAPIIdentifier.MainThreadDecorations);
    }
    registerFileDecorationProvider(provider, extensionId) {
        const handle = ExtHostDecorations._handlePool++;
        this._provider.set(handle, { provider, extensionId });
        this.proxy.$registerDecorationProvider(handle, extensionId);
        const listener = provider.onDidChangeFileDecorations &&
            provider.onDidChangeFileDecorations((e) => {
                if (!e) {
                    this.proxy.$onDidChange(handle, null);
                    return;
                }
                const array = asArray(e);
                if (array.length <= ExtHostDecorations._maxEventSize) {
                    this.proxy.$onDidChange(handle, array);
                    return;
                }
                // too many resources per event. pick one resource per folder, starting
                // with parent folders
                this.logger.warn('[Decorations] CAPPING events from decorations provider', extensionId, array.length);
                const mapped = array.map((uri) => ({ uri, rank: count(uri.path, '/') }));
                const groups = groupBy(mapped, (a, b) => a.rank - b.rank || compare(a.uri.path, b.uri.path));
                const picked = [];
                outer: for (const uris of groups) {
                    let lastDirname;
                    for (const obj of uris) {
                        const myDirname = dirname(obj.uri.path);
                        if (lastDirname !== myDirname) {
                            lastDirname = myDirname;
                            if (picked.push(obj.uri) >= ExtHostDecorations._maxEventSize) {
                                break outer;
                            }
                        }
                    }
                }
                this.proxy.$onDidChange(handle, picked);
            });
        return (0, ide_core_common_1.toDisposable)(() => {
            listener === null || listener === void 0 ? void 0 : listener.dispose();
            this.proxy.$unregisterDecorationProvider(handle);
            this._provider.delete(handle);
        });
    }
    $provideFileDecorations(requests, token) {
        const result = Object.create(null);
        return Promise.all(requests.map((request) => {
            const { handle, uri, id } = request;
            const entry = this._provider.get(handle);
            if (!entry) {
                // might have been unregistered in the meantime
                return undefined;
            }
            const { provider, extensionId } = entry;
            if (isFileDecorationProvider(provider)) {
                return Promise.resolve(provider.provideFileDecoration(ide_core_common_1.Uri.revive(uri), token)).then((data) => {
                    var _a;
                    if (!data) {
                        return;
                    }
                    try {
                        result[id] = [(_a = data.propagate) !== null && _a !== void 0 ? _a : false, data.tooltip, data.badge, data.color];
                        ext_types_1.FileDecoration.validate(data);
                    }
                    catch (e) {
                        this.logger.warn(`INVALID decoration from extension '${extensionId}'. ${e}`);
                    }
                }, (err) => {
                    this.logger.error(err);
                });
            }
        })).then(() => result);
    }
}
exports.ExtHostDecorations = ExtHostDecorations;
ExtHostDecorations._handlePool = 0;
ExtHostDecorations._maxEventSize = 250;
//# sourceMappingURL=ext.host.decoration.js.map