"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (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.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const ts = __importStar(require("typescript"));
const nodePath = __importStar(require("path"));
const tsconfig_paths_1 = require("tsconfig-paths");
// ugly hack because passing TSCONFIG_PATH_EXTENSIONS to tsconfig-path doens't really work?
require.extensions['.ts'] = require.extensions['.js'];
require.extensions['.tsx'] = require.extensions['.js'];
function visitSourceFile(sourceFile, context, matchPathFunc) {
    function isPathRelative(path) {
        return path.startsWith('./') || path.startsWith('../');
    }
    function getModuleSpecifierValue(specifier) {
        // it's hard, so we'll just assume leading width is the length of the trailing width
        const value = specifier
            .getText()
            .substr(specifier.getLeadingTriviaWidth(), specifier.getWidth() - specifier.getLeadingTriviaWidth() * 2);
        return value;
    }
    function isImportExportSpecifierRelative(node) {
        if (node.moduleSpecifier && node.moduleSpecifier.getSourceFile()) {
            return isPathRelative(getModuleSpecifierValue(node.moduleSpecifier));
        }
        return false;
    }
    function relativizeImportExportNode(node, sourceFilePath) {
        if (!node.moduleSpecifier || !node.moduleSpecifier.getSourceFile()) {
            return node;
        }
        const specifierValue = getModuleSpecifierValue(node.moduleSpecifier);
        const matchedPath = matchPathFunc(specifierValue);
        if (matchedPath) {
            const replacePath = nodePath.relative(sourceFilePath, matchedPath);
            // replace the module specifier
            node.moduleSpecifier = ts.createLiteral(isPathRelative(replacePath) ? replacePath : `./${replacePath}`);
        }
        return node;
    }
    function visitImportExportNode(node) {
        if (!node.moduleSpecifier || isImportExportSpecifierRelative(node)) {
            return node;
        }
        // const sourceFilePath = sourceFile.fileName
        const sourceFilePath = nodePath.dirname(sourceFile.fileName);
        return relativizeImportExportNode(node, sourceFilePath);
    }
    function visitNode(node) {
        if (ts.isExportDeclaration(node) || ts.isImportDeclaration(node)) {
            return visitImportExportNode(node);
        }
        return node;
    }
    function visitNodeAndChildren(node) {
        if (node == null) {
            return node;
        }
        node = visitNode(node);
        return ts.visitEachChild(node, (childNode) => visitNodeAndChildren(childNode), context);
    }
    return visitNodeAndChildren(sourceFile);
}
const transformerFactory = (context) => {
    const compilerOptions = context.getCompilerOptions();
    const absoluteBaseUrl = compilerOptions.baseUrl;
    const matchPathFunc = tsconfig_paths_1.createMatchPath(absoluteBaseUrl, compilerOptions.paths || {});
    return (file) => visitSourceFile(file, context, matchPathFunc);
};
const transform = () => transformerFactory;
exports.default = transform;
//# sourceMappingURL=absoluteToRelative.js.map