"use strict";
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
    result["default"] = 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'];
const TSCONFIG_PATH_EXTENSIONS = ['.ts', '.tsx'];
// force extra extensions onto matchPath
// this doesn't resolve the supplied extensions, for some reason
// import { fileExistsSync, readJsonFromDiskSync } from 'tsconfig-paths/lib/filesystem';
// const matchPath = (value: string) => matchPathFunc(value, readJsonFromDiskSync, fileExistsSync, TSCONFIG_PATH_EXTENSIONS)
const transform = (program) => transformerFactory;
const transformerFactory = context => {
    const compilerOptions = context.getCompilerOptions();
    const absoluteBaseUrl = compilerOptions.baseUrl;
    const matchPathFunc = tsconfig_paths_1.createMatchPath(
    // @ts-ignore
    absoluteBaseUrl, compilerOptions.paths || {});
    return file => visitSourceFile(file, context, matchPathFunc);
};
function visitSourceFile(sourceFile, context, matchPathFunc) {
    return visitNodeAndChildren(sourceFile);
    function visitNodeAndChildren(node) {
        if (node == null) {
            return node;
        }
        node = visitNode(node);
        return ts.visitEachChild(node, childNode => visitNodeAndChildren(childNode), context);
    }
    function visitNode(node) {
        if (ts.isExportDeclaration(node) || ts.isImportDeclaration(node)) {
            return visitImportExportNode(node);
        }
        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 isImportExportSpecifierRelative(node) {
        if (node.moduleSpecifier && node.moduleSpecifier.getSourceFile()) {
            return isPathRelative(getModuleSpecifierValue(node.moduleSpecifier));
        }
        return false;
    }
    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 isPathRelative(path) {
        return path.startsWith('./') || path.startsWith('../');
    }
    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}`);
        }
        else {
        }
        return node;
    }
}
exports.default = transform;
//# sourceMappingURL=absoluteToRelative.js.map