"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.extractAllPackageFiles = exports.extractPackageFile = void 0;
const logger_1 = require("../../../logger");
const fs_1 = require("../../../util/fs");
const common_1 = require("../../datasource/pypi/common");
const extract_1 = require("../pip_requirements/extract");
const pip_setup_1 = require("../pip_setup");
const common_2 = require("./common");
const utils_1 = require("./utils");
function matchManager(filename) {
    if (filename.endsWith('setup.py')) {
        return 'pip_setup';
    }
    if (filename.endsWith('setup.cfg')) {
        return 'setup-cfg';
    }
    if (filename.endsWith('pyproject.toml')) {
        return 'pep621';
    }
    // naive, could be improved, maybe use pip_requirements.fileMatch
    if (filename.endsWith('.in')) {
        return 'pip_requirements';
    }
    return 'unknown';
}
function extractPackageFile(content, packageFile, _config) {
    logger_1.logger.trace('pip-compile.extractPackageFile()');
    const manager = matchManager(packageFile);
    switch (manager) {
        case 'pip_setup':
            return (0, pip_setup_1.extractPackageFile)(content, packageFile, _config);
        case 'pip_requirements':
            return (0, extract_1.extractPackageFile)(content);
        case 'unknown':
            logger_1.logger.warn({ packageFile }, `pip-compile: could not determine manager for source file`);
            return null;
        default:
            logger_1.logger.warn({ packageFile, manager }, `pip-compile: support for manager is not yet implemented`);
            return null;
    }
}
exports.extractPackageFile = extractPackageFile;
async function extractAllPackageFiles(config, fileMatches) {
    logger_1.logger.trace('pip-compile.extractAllPackageFiles()');
    const lockFileArgs = new Map();
    const depsBetweenFiles = [];
    // for debugging only ^^^ (for now)
    const packageFiles = new Map();
    for (const fileMatch of fileMatches) {
        const fileContent = await (0, fs_1.readLocalFile)(fileMatch, 'utf8');
        if (!fileContent) {
            logger_1.logger.debug(`pip-compile: no content found for fileMatch ${fileMatch}`);
            continue;
        }
        let compileArgs;
        try {
            compileArgs = (0, common_2.extractHeaderCommand)(fileContent, fileMatch);
        }
        catch (error) {
            logger_1.logger.warn({ fileMatch }, `pip-compile: ${error.message}`);
            continue;
        }
        lockFileArgs.set(fileMatch, compileArgs);
        for (const constraint in compileArgs.constraintsFiles) {
            // TODO(not7cd): handle constraints
            /* istanbul ignore next */
            depsBetweenFiles.push({
                sourceFile: constraint,
                outputFile: fileMatch,
                type: 'constraint',
            });
        }
        const lockedDeps = (0, extract_1.extractPackageFile)(fileContent)?.deps;
        if (!lockedDeps) {
            logger_1.logger.debug({ fileMatch }, 'pip-compile: Failed to extract dependencies from lock file');
            continue;
        }
        for (const packageFile of compileArgs.sourceFiles) {
            depsBetweenFiles.push({
                sourceFile: packageFile,
                outputFile: fileMatch,
                type: 'requirement',
            });
            if (fileMatches.includes(packageFile)) {
                // TODO(not7cd): do something about it
                logger_1.logger.warn({ sourceFile: packageFile, lockFile: fileMatch }, 'pip-compile: lock file acts as source file for another lock file');
                continue;
            }
            if (packageFiles.has(packageFile)) {
                logger_1.logger.debug(`pip-compile: ${packageFile} used in multiple output files`);
                packageFiles.get(packageFile).lockFiles.push(fileMatch);
                continue;
            }
            const content = await (0, fs_1.readLocalFile)(packageFile, 'utf8');
            if (!content) {
                logger_1.logger.debug(`pip-compile: No content for source file ${packageFile}`);
                continue;
            }
            const packageFileContent = extractPackageFile(content, packageFile, config);
            if (packageFileContent) {
                for (const dep of packageFileContent.deps) {
                    const lockedVersion = lockedDeps?.find((lockedDep) => (0, common_1.normalizeDepName)(lockedDep.depName) ===
                        (0, common_1.normalizeDepName)(dep.depName))?.currentVersion;
                    if (lockedVersion) {
                        dep.lockedVersion = lockedVersion;
                    }
                    else {
                        logger_1.logger.warn({ depName: dep.depName, lockFile: fileMatch }, 'pip-compile: dependency not found in lock file');
                    }
                }
                packageFiles.set(packageFile, {
                    ...packageFileContent,
                    lockFiles: [fileMatch],
                    packageFile,
                });
            }
            else {
                logger_1.logger.warn({ packageFile }, 'pip-compile: failed to find dependencies in source file');
            }
        }
    }
    // TODO(not7cd): sort by requirement layering (-r -c within .in files)
    if (packageFiles.size === 0) {
        return null;
    }
    logger_1.logger.debug('pip-compile: dependency graph:\n' +
        (0, utils_1.generateMermaidGraph)(depsBetweenFiles, lockFileArgs));
    return Array.from(packageFiles.values());
}
exports.extractAllPackageFiles = extractAllPackageFiles;
//# sourceMappingURL=extract.js.map