"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parse = void 0;
const tslib_1 = require("tslib");
const good_enough_parser_1 = require("good-enough-parser");
const cpan_1 = require("../../datasource/cpan");
const github_tags_1 = require("../../datasource/github-tags");
const perlVersioning = tslib_1.__importStar(require("../../versioning/perl"));
const language_1 = require("./language");
// requires perl, '5.36.1';
// requires 'perl' => 5.036001;
const perlVersionMatch = good_enough_parser_1.query
    .sym('requires')
    .alt(good_enough_parser_1.query.sym('perl'), good_enough_parser_1.query.str('perl'))
    .alt(good_enough_parser_1.query.op(','), good_enough_parser_1.query.op('=>'))
    .alt(good_enough_parser_1.query.num((ctx, { value: perlVersion }) => ({ ...ctx, perlVersion })), good_enough_parser_1.query.str((ctx, { value: perlVersion }) => ({ ...ctx, perlVersion })))
    .op(';')
    .handler((ctx) => {
    if (ctx.perlVersion) {
        ctx.deps.push({
            depName: 'perl',
            packageName: 'Perl/perl5',
            currentValue: ctx.perlVersion,
            datasource: github_tags_1.GithubTagsDatasource.id,
            versioning: perlVersioning.id,
            extractVersion: '^v(?<version>\\S+)',
        });
    }
    return ctx;
});
const requirementMatch = good_enough_parser_1.query.sym(/^(?:requires|recommends|suggests)$/);
const phasedRequiresMatch = good_enough_parser_1.query.sym(/^(?:configure|build|test|author)_requires$/, (ctx, { value: phase }) => {
    ctx.tempPhase = phase.replace(/_requires/, '').replace(/author/, 'develop');
    return ctx;
});
// requires 'Foo::Bar';
//
// requires 'Foo::Bar', '1.23';
// recommends 'Foo::Bar', '1.23';
// suggests 'Foo::Bar', '1.23';
//
// configure_requires 'Foo::Bar' => 1.023;
// build_requires 'Foo::Bar' => 1.023;
// test_requires 'Foo::Bar' => 1.023;
// author_requires 'Foo::Bar' => 1.023;
const moduleMatch = good_enough_parser_1.query
    .alt(requirementMatch, phasedRequiresMatch)
    .str((ctx, { value: depName }) => ({ ...ctx, depName }))
    .opt(good_enough_parser_1.query.alt(good_enough_parser_1.query.op(','), good_enough_parser_1.query.op('=>')).alt(good_enough_parser_1.query.num((ctx, { value: currentValue }) => ({ ...ctx, currentValue })), good_enough_parser_1.query.str((ctx, { value }) => {
    const currentValue = value.replace(/^(?:\s*(?:==|>=|>))?\s*v?/, '');
    return { ...ctx, currentValue };
})))
    .op(';')
    .handler((ctx) => {
    const { phase, tempPhase, depName, currentValue } = ctx;
    delete ctx.tempPhase;
    delete ctx.depName;
    delete ctx.currentValue;
    if (depName) {
        const dep = {
            depName,
        };
        if (currentValue) {
            dep.currentValue = currentValue;
        }
        else {
            dep.skipReason = 'no-version';
        }
        if (phase) {
            dep.depType = phase;
        }
        else if (tempPhase) {
            dep.depType = tempPhase;
        }
        dep.datasource = cpan_1.CpanDatasource.id;
        ctx.deps.push(dep);
    }
    return ctx;
});
const phaseRegex = /^(?:configure|build|test|runtime|develop)/;
const phaseMatch = good_enough_parser_1.query.alt(good_enough_parser_1.query.sym(phaseRegex, (ctx, { value: phase }) => ({ ...ctx, phase })), good_enough_parser_1.query.str(phaseRegex, (ctx, { value: phase }) => ({ ...ctx, phase })));
// on 'configure' => sub {
// on build => sub {
// on 'test' => sub {
// on runtime => sub {
// on 'develop' => sub {
const onMatch = good_enough_parser_1.query
    .sym('on')
    .join(phaseMatch)
    .op('=>')
    .sym('sub')
    .tree({
    type: 'wrapped-tree',
    maxDepth: 1,
    search: moduleMatch,
})
    .handler((ctx) => {
    delete ctx.phase;
    return ctx;
});
const query = good_enough_parser_1.query.tree({
    type: 'root-tree',
    maxDepth: 4,
    search: good_enough_parser_1.query.alt(perlVersionMatch, moduleMatch, onMatch),
});
function parse(content) {
    return language_1.cpanfile.query(content, query, {
        deps: [],
    });
}
exports.parse = parse;
//# sourceMappingURL=parser.js.map