import {
    codeFixAll,
    createCodeFixAction,
    createCodeFixActionWithoutFixAll,
    createFileTextChanges,
    registerCodeFix,
} from "../_namespaces/ts.codefix.js";
import {
    CodeFixAction,
    createTextChange,
    createTextSpan,
    createTextSpanFromBounds,
    DiagnosticCategory,
    Diagnostics,
    getLineAndCharacterOfPosition,
    getNewLineOrDefaultFromHost,
    isCheckJsEnabledForFile,
    isInJSFile,
    mapDefined,
    SourceFile,
    textChanges,
    tryAddToSet,
} from "../_namespaces/ts.js";

const fixName = "disableJsDiagnostics";
const fixId = "disableJsDiagnostics";
const errorCodes = mapDefined(Object.keys(Diagnostics) as readonly (keyof typeof Diagnostics)[], key => {
    const diag = Diagnostics[key];
    return diag.category === DiagnosticCategory.Error ? diag.code : undefined;
});

registerCodeFix({
    errorCodes,
    getCodeActions: function getCodeActionsToDisableJsDiagnostics(context) {
        const { sourceFile, program, span, host, formatContext } = context;

        if (!isInJSFile(sourceFile) || !isCheckJsEnabledForFile(sourceFile, program.getCompilerOptions())) {
            return undefined;
        }

        const newLineCharacter = sourceFile.checkJsDirective ? "" : getNewLineOrDefaultFromHost(host, formatContext.options);
        const fixes: CodeFixAction[] = [
            // fixId unnecessary because adding `// @ts-nocheck` even once will ignore every error in the file.
            createCodeFixActionWithoutFixAll(
                fixName,
                [createFileTextChanges(sourceFile.fileName, [
                    createTextChange(
                        sourceFile.checkJsDirective
                            ? createTextSpanFromBounds(sourceFile.checkJsDirective.pos, sourceFile.checkJsDirective.end)
                            : createTextSpan(0, 0),
