"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CodeActionAdapter = void 0;
const tslib_1 = require("tslib");
const ide_core_common_1 = require("@opensumi/ide-core-common");
const arrays_1 = require("@opensumi/ide-utils/lib/arrays");
const Converter = tslib_1.__importStar(require("../../../../common/vscode/converter"));
const ext_types_1 = require("../../../../common/vscode/ext-types");
class CodeActionAdapter {
    constructor(provider, document, diagnostics) {
        this.provider = provider;
        this.document = document;
        this.diagnostics = diagnostics;
        this._cache = new ide_core_common_1.Cache('CodeAction');
        this._disposables = new Map();
    }
    async provideCodeActions(resource, rangeOrSelection, context, commandConverter, token) {
        const document = this.document.getDocumentData(resource);
        if (!document) {
            return Promise.reject(new Error(`There are no document for ${resource}`));
        }
        const doc = document.document;
        const ran = CodeActionAdapter._isSelection(rangeOrSelection)
            ? Converter.Selection.to(rangeOrSelection)
            : Converter.Range.to(rangeOrSelection);
        const allDiagnostics = [];
        for (const diagnostic of this.diagnostics.getDiagnostics(resource)) {
            if (ran.intersection(diagnostic.range)) {
                const newLen = allDiagnostics.push(diagnostic);
                if (newLen > CodeActionAdapter._maxCodeActionsPerFile) {
                    break;
                }
            }
        }
        const codeActionContext = {
            diagnostics: allDiagnostics,
            only: context.only ? new ext_types_1.CodeActionKind(context.only) : undefined,
            triggerKind: Converter.CodeActionTriggerKind.to(context.trigger),
        };
        let cacheId;
        const actions = await Promise.resolve(this.provider.provideCodeActions(doc, ran, codeActionContext, token)).then((commandsOrActions) => {
            var _a;
            if (!Array.isArray(commandsOrActions) || commandsOrActions.length === 0) {
                return undefined;
            }
            cacheId = this._cache.add(commandsOrActions);
            const disposables = new ide_core_common_1.DisposableStore();
            this._disposables.set(cacheId, disposables);
            const actions = [];
            for (let i = 0; i < commandsOrActions.length; i++) {
                const candidate = commandsOrActions[i];
                if (!candidate) {
                    continue;
                }
                if (CodeActionAdapter._isCommand(candidate)) {
                    actions.push({
                        title: candidate.title || '',
                        command: commandConverter.toInternal(candidate, disposables),
                    });
                }
                else {
                    if (codeActionContext.only) {
                        if (!candidate.kind) {
                            // TODO: 当 kind 是 Empty 时， kind === ''，此时似乎不应该提示这个 warning
                            // eslint-disable-next-line no-console
                            console.warn(`Code actions of kind '${codeActionContext.only.value}' requested but returned code action does not have a 'kind'. Code action will be dropped. Please set 'CodeAction.kind'.`);
                        }
                        else if (!codeActionContext.only.contains(candidate.kind)) {
                            // eslint-disable-next-line no-console
                            console.warn(`Code actions of kind '${codeActionContext.only.value}' requested but returned code action is of kind '${candidate.kind.value}'. Code action will be dropped. Please check 'CodeActionContext.only' to only return requested code action.`);
                        }
                    }
                    actions.push({
                        cacheId: [cacheId, i],
                        title: candidate.title,
                        command: candidate.command && commandConverter.toInternal(candidate.command, disposables),
                        diagnostics: candidate.diagnostics && candidate.diagnostics.map(Converter.Diagnostic.toMarker),
                        edit: candidate.edit && Converter.WorkspaceEdit.from(candidate.edit),
                        kind: candidate.kind && candidate.kind.value,
                        isPreferred: candidate.isPreferred,
                        isAI: candidate.isAI,
                        disabled: (_a = candidate.disabled) === null || _a === void 0 ? void 0 : _a.reason,
                        ranges: candidate.ranges ? (0, arrays_1.coalesce)(candidate.ranges.map(Converter.Range.from)) : [],
                    });
                }
            }
            return actions;
        });
        if (actions) {
            return {
                actions,
                cacheId: cacheId,
            };
        }
        return undefined;
    }
    async resolveCodeAction(id, token) {
        var _a;
        const [sessionId, itemId] = id;
        const item = this._cache.get(sessionId, itemId);
        if (!item || CodeActionAdapter._isCommand(item)) {
            return undefined; // code actions only!
        }
        if (!this.provider.resolveCodeAction) {
            return; // this should not happen...
        }
        const resolvedItem = (_a = (await this.provider.resolveCodeAction(item, token))) !== null && _a !== void 0 ? _a : item;
        return (resolvedItem === null || resolvedItem === void 0 ? void 0 : resolvedItem.edit) ? Converter.WorkspaceEdit.from(resolvedItem.edit) : undefined;
    }
    releaseCodeActions(cachedId) {
        var _a;
        (_a = this._disposables.get(cachedId)) === null || _a === void 0 ? void 0 : _a.dispose();
        this._disposables.delete(cachedId);
        this._cache.delete(cachedId);
    }
    static _isCommand(smth) {
        return typeof smth.command === 'string';
    }
    static _isSelection(obj) {
        return (obj &&
            typeof obj.selectionStartLineNumber === 'number' &&
            typeof obj.selectionStartColumn === 'number' &&
            typeof obj.positionLineNumber === 'number' &&
            typeof obj.positionColumn === 'number');
    }
}
exports.CodeActionAdapter = CodeActionAdapter;
CodeActionAdapter._maxCodeActionsPerFile = 1000;
//# sourceMappingURL=code-action.js.map