"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.prepareVueTsc = void 0;
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const proxyPath = require.resolve('vue-tsc/out/proxy');
const textToReplace = [
    {
        target: `ts.supportedTSExtensions = [[".ts", ".tsx", ".d.ts"], [".cts", ".d.cts"], [".mts", ".d.mts"]];`,
        replacement: `ts.supportedTSExtensions = [[".ts", ".tsx", ".d.ts"], [".cts", ".d.cts"], [".mts", ".d.mts"], [".vue"]];`,
    },
    {
        target: `ts.supportedJSExtensions = [[".js", ".jsx"], [".mjs"], [".cjs"]];`,
        replacement: `ts.supportedJSExtensions = [[".js", ".jsx"], [".mjs"], [".cjs"], [".vue"]];`,
    },
    {
        target: `var allSupportedExtensions = [[".ts", ".tsx", ".d.ts", ".js", ".jsx"], [".cts", ".d.cts", ".cjs"], [".mts", ".d.mts", ".mjs"]];`,
        replacement: `var allSupportedExtensions = [[".ts", ".tsx", ".d.ts", ".js", ".jsx"], [".cts", ".d.cts", ".cjs"], [".mts", ".d.mts", ".mjs"], [".vue"]];`,
    },
    // proxy createProgram apis
    {
        target: `function createIncrementalProgram(_a) {`,
        replacement: `function createIncrementalProgram(_a) { console.error('incremental mode is not yet supported'); throw 'incremental mode is not yet supported';`,
    },
    {
        target: `function createProgram(rootNamesOrOptions, _options, _host, _oldProgram, _configFileParsingDiagnostics) {`,
        replacement: `function createProgram(rootNamesOrOptions, _options, _host, _oldProgram, _configFileParsingDiagnostics) { return require(${JSON.stringify(proxyPath)}).createProgramProxy(...arguments);`,
    },
    {
        target: `ts.executeCommandLine(ts.sys, ts.noop, ts.sys.args);`,
        replacement: `module.exports = ts`,
    },
];
function prepareVueTsc() {
    // 1. copy typescript to folder
    const tsDirTo = path_1.default.resolve(__dirname, 'typescript-vue-tsc');
    let shouldPrepare = false;
    const exist = fs_1.default.existsSync(tsDirTo);
    if (exist) {
        const toDirVersion = require(path_1.default.resolve(tsDirTo, 'package.json')).version;
        const tsVersion = require('typescript/package.json').version;
        if (toDirVersion !== tsVersion) {
            shouldPrepare = true;
            rimraf(tsDirTo);
        }
    }
    else {
        shouldPrepare = true;
    }
    if (shouldPrepare) {
        fs_1.default.mkdirSync(tsDirTo);
        const tsPath = path_1.default.resolve(require.resolve('typescript'), '../..');
        copyDirRecursively(tsPath, tsDirTo);
        // 2. sync modification of lib/tsc.js with vue-tsc
        const tscJs = require.resolve(path_1.default.resolve(tsDirTo, 'lib/tsc.js'));
        modifyFileText(tscJs, textToReplace);
    }
    return { tsDirTo };
}
exports.prepareVueTsc = prepareVueTsc;
function copyDirRecursively(src, dest) {
    const files = fs_1.default.readdirSync(src, { withFileTypes: true });
    for (const file of files) {
        const srcPath = path_1.default.join(src, file.name);
        const destPath = path_1.default.join(dest, file.name);
        if (file.isDirectory()) {
            fs_1.default.mkdirSync(destPath, { recursive: true });
            copyDirRecursively(srcPath, destPath);
        }
        else {
            fs_1.default.copyFileSync(srcPath, destPath);
        }
    }
}
function modifyFileText(filePath, textToReplace) {
    const text = fs_1.default.readFileSync(filePath, 'utf8');
    let newText = text;
    for (const { target, replacement } of textToReplace) {
        newText = newText.replace(target, replacement);
    }
    fs_1.default.writeFileSync(filePath, newText);
}
/**
 * https://stackoverflow.com/a/42505874
 */
function rimraf(dir_path) {
    if (fs_1.default.existsSync(dir_path)) {
        fs_1.default.readdirSync(dir_path).forEach((entry) => {
            const entry_path = path_1.default.join(dir_path, entry);
            if (fs_1.default.lstatSync(entry_path).isDirectory()) {
                rimraf(entry_path);
            }
            else {
                fs_1.default.unlinkSync(entry_path);
            }
        });
        fs_1.default.rmdirSync(dir_path);
    }
}
