"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.register = void 0;
const rename_1 = require("./rename");
const fixNames = __importStar(require("../utils/fixNames"));
const getFormatCodeSettings_1 = require("../configs/getFormatCodeSettings");
const getUserPreferences_1 = require("../configs/getUserPreferences");
const shared_1 = require("../shared");
const codeActionResolve_1 = require("./codeActionResolve");
function register(ctx) {
    let resolveCommandSupport = ctx.env.clientCapabilities?.textDocument?.codeAction?.resolveSupport?.properties?.includes('command');
    let resolveEditSupport = ctx.env.clientCapabilities?.textDocument?.codeAction?.resolveSupport?.properties?.includes('edit');
    if (!ctx.env.clientCapabilities) {
        resolveCommandSupport = true;
        resolveEditSupport = true;
    }
    return async (uri, range, context) => {
        const document = ctx.getTextDocument(uri);
        if (!document)
            return;
        const [formatOptions, preferences] = await Promise.all([
            (0, getFormatCodeSettings_1.getFormatCodeSettings)(ctx, document),
            (0, getUserPreferences_1.getUserPreferences)(ctx, document),
        ]);
        const fileName = ctx.env.uriToFileName(document.uri);
        const start = document.offsetAt(range.start);
        const end = document.offsetAt(range.end);
        let result = [];
        const onlyQuickFix = matchOnlyKind(`${'quickfix'}.ts`);
        if (!context.only || onlyQuickFix) {
            for (const error of context.diagnostics) {
                const codeFixes = (0, shared_1.safeCall)(() => ctx.typescript.languageService.getCodeFixesAtPosition(fileName, document.offsetAt(error.range.start), document.offsetAt(error.range.end), [Number(error.code)], formatOptions, preferences)) ?? [];
                for (const codeFix of codeFixes) {
                    result = result.concat(transformCodeFix(codeFix, [error], onlyQuickFix ?? ''));
                }
            }
        }
        if (context.only) {
            for (const only of context.only) {
                if (only.split('.')[0] === 'refactor') {
                    const refactors = (0, shared_1.safeCall)(() => ctx.typescript.languageService.getApplicableRefactors(fileName, { pos: start, end: end }, preferences, undefined, only)) ?? [];
                    for (const refactor of refactors) {
                        result = result.concat(transformRefactor(refactor));
                    }
                }
            }
        }
        else {
            const refactors = (0, shared_1.safeCall)(() => ctx.typescript.languageService.getApplicableRefactors(fileName, { pos: start, end: end }, preferences, undefined, undefined)) ?? [];
            for (const refactor of refactors) {
                result = result.concat(transformRefactor(refactor));
            }
        }
        const onlySourceOrganizeImports = matchOnlyKind(`${'source.organizeImports'}.ts`);
        if (onlySourceOrganizeImports) {
            const action = {
                title: 'Organize Imports',
                kind: onlySourceOrganizeImports,
            };
            const data = {
                type: 'organizeImports',
                uri,
                fileName,
            };
            if (resolveEditSupport) {
                action.data = data;
            }
            else {
                (0, codeActionResolve_1.resolveOrganizeImportsCodeAction)(ctx, action, data, formatOptions, preferences);
            }
            result.push(action);
        }
        const onlySourceFixAll = matchOnlyKind(`${'source.fixAll'}.ts`);
        if (onlySourceFixAll) {
            const action = {
                title: 'Fix All',
                kind: onlySourceFixAll,
            };
            const data = {
                uri,
                type: 'fixAll',
                fileName,
                fixIds: [
                    fixNames.classIncorrectlyImplementsInterface,
                    fixNames.awaitInSyncFunction,
                    fixNames.unreachableCode,
                ],
            };
            if (resolveEditSupport) {
                action.data = data;
            }
            else {
                (0, codeActionResolve_1.resolveFixAllCodeAction)(ctx, action, data, formatOptions, preferences);
            }
            result.push(action);
        }
        const onlyRemoveUnused = matchOnlyKind(`${'source'}.removeUnused.ts`);
        if (onlyRemoveUnused) {
            const action = {
                title: 'Remove all unused code',
                kind: onlyRemoveUnused,
            };
            const data = {
                uri,
                type: 'fixAll',
                fileName,
                fixIds: [
                    // not working and throw
                    fixNames.unusedIdentifier,
                    // TODO: remove patching
                    'unusedIdentifier_prefix',
                    'unusedIdentifier_deleteImports',
                    'unusedIdentifier_delete',
                    'unusedIdentifier_infer',
                ],
            };
            if (resolveEditSupport) {
                action.data = data;
            }
            else {
                (0, codeActionResolve_1.resolveFixAllCodeAction)(ctx, action, data, formatOptions, preferences);
            }
            result.push(action);
        }
        const onlyAddMissingImports = matchOnlyKind(`${'source'}.addMissingImports.ts`);
        if (onlyAddMissingImports) {
            const action = {
                title: 'Add all missing imports',
                kind: onlyAddMissingImports,
            };
            const data = {
                uri,
                type: 'fixAll',
                fileName,
                fixIds: [
                    // not working and throw
                    fixNames.fixImport,
                    // TODO: remove patching
                    'fixMissingImport',
                ],
            };
            if (resolveEditSupport) {
                action.data = data;
            }
            else {
                (0, codeActionResolve_1.resolveFixAllCodeAction)(ctx, action, data, formatOptions, preferences);
            }
            result.push(action);
        }
        for (const codeAction of result) {
            if (codeAction.diagnostics === undefined) {
                codeAction.diagnostics = context.diagnostics;
            }
        }
        return result;
        function matchOnlyKind(kind) {
            if (context.only) {
                for (const only of context.only) {
                    const a = only.split('.');
                    const b = kind.split('.');
                    if (a.length <= b.length) {
                        let matchNums = 0;
                        for (let i = 0; i < a.length; i++) {
                            if (a[i] == b[i]) {
                                matchNums++;
                            }
                        }
                        if (matchNums === a.length)
                            return only;
                    }
                }
            }
        }
        function transformCodeFix(codeFix, diagnostics, kind) {
            const edit = (0, rename_1.fileTextChangesToWorkspaceEdit)(codeFix.changes, ctx);
            const codeActions = [];
            const fix = {
                title: codeFix.description,
                kind,
                edit,
            };
            fix.diagnostics = diagnostics;
            codeActions.push(fix);
            if (codeFix.fixAllDescription && codeFix.fixId) {
                const fixAll = {
                    title: codeFix.fixAllDescription,
                    kind,
                };
                const data = {
                    uri,
                    type: 'fixAll',
                    fileName,
                    fixIds: [codeFix.fixId],
                };
                if (resolveEditSupport) {
                    fixAll.data = data;
                }
                else {
                    (0, codeActionResolve_1.resolveFixAllCodeAction)(ctx, fixAll, data, formatOptions, preferences);
                }
                fixAll.diagnostics = diagnostics;
                codeActions.push(fixAll);
            }
            return codeActions;
        }
        function transformRefactor(refactor) {
            const codeActions = [];
            for (const action of refactor.actions) {
                const codeAction = {
                    title: action.description,
                    kind: action.kind,
                };
                if (action.notApplicableReason) {
                    codeAction.disabled = { reason: action.notApplicableReason };
                }
                if (refactor.inlineable) {
                    codeAction.isPreferred = true;
                }
                const data = {
                    uri,
                    type: 'refactor',
                    fileName,
                    range: { pos: start, end: end },
                    refactorName: refactor.name,
                    actionName: action.name,
                };
                if (resolveCommandSupport && resolveEditSupport) {
                    codeAction.data = data;
                }
                else if (!codeAction.disabled && document) {
                    (0, codeActionResolve_1.resolveRefactorCodeAction)(ctx, codeAction, data, document, formatOptions, preferences);
                }
                codeActions.push(codeAction);
            }
            return codeActions;
        }
    };
}
exports.register = register;
//# sourceMappingURL=codeAction.js.map