"use strict";
/*
 * Copyright © 2020 Atomist, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.mapTest = exports.CreatePushTests = exports.mapTests = void 0;
const changeCase = require("change-case");
const commit_1 = require("../../../api-helper/pushtest/commit");
const materialChangeTest_1 = require("../../../api-helper/pushtest/materialChangeTest");
const goalTest_1 = require("../../../api/mapping/goalTest");
const PushTest_1 = require("../../../api/mapping/PushTest");
const commonPushTests_1 = require("../../../api/mapping/support/commonPushTests");
const pushTestUtils_1 = require("../../../api/mapping/support/pushTestUtils");
const types_1 = require("../../../typings/types");
const isSkillConfigured_1 = require("../../mapping/pushtest/isSkillConfigured");
const array_1 = require("../../util/misc/array");
const util_1 = require("./util");
async function mapTests(tests, additionalTests, extensionTests) {
    const newTests = [];
    for (const t of array_1.toArray(tests || [])) {
        const test = typeof t !== "string" && !Array.isArray(t) ? util_1.camelCase(t) : t;
        newTests.push(await mapTest(test, additionalTests, extensionTests));
    }
    return newTests;
}
exports.mapTests = mapTests;
const HasFile = async (test) => {
    if (!!test.hasFile) {
        return commonPushTests_1.hasFile(test.hasFile);
    }
    return undefined;
};
const IsRepo = async (test) => {
    if (!!test.isRepo) {
        return commonPushTests_1.isRepo(typeof test.isRepo === "string" ? new RegExp(test.isRepo) : test.isRepo);
    }
    return undefined;
};
const IsBranch = async (test) => {
    if (!!test.isBranch) {
        return commonPushTests_1.isBranch(typeof test.isBranch === "string" ? new RegExp(test.isBranch) : test.isBranch);
    }
    return undefined;
};
const IsDefaultBranch = async (test) => {
    if (["isDefaultBranch", "toDefaultBranch"].includes(changeCase.camel(test))) {
        return commonPushTests_1.ToDefaultBranch;
    }
    return undefined;
};
const IsSkillConfigured = async (test) => {
    if (!!test.isSkillConfigured) {
        const sc = test.isSkillConfigured;
        return isSkillConfigured_1.isSkillConfigured({
            hasCommit: sc.hasCommit,
            hasFile: sc.hasFile,
            isBranch: sc.isBranch,
            isDefaultBranch: sc.isDefaultBranch,
        });
    }
    return undefined;
};
const IsGoal = async (test, additionalTests, extensionTests) => {
    const onGoal = test.isGoal || test.onGoal;
    if (!!onGoal) {
        return goalTest_1.isGoal({
            name: getStringOrRegexp(onGoal.name),
            state: onGoal.state || types_1.SdmGoalState.success,
            pushTest: onGoal.test ? await mapTest(onGoal.test, additionalTests, extensionTests) : undefined,
            output: getStringOrRegexp(onGoal.output),
            data: getStringOrRegexp(onGoal.data),
        });
    }
    return undefined;
};
const IsMaterialChange = async (test) => {
    if (!!test.isMaterialChange) {
        return materialChangeTest_1.isMaterialChange({
            directories: array_1.toArray(test.isMaterialChange.directories),
            extensions: array_1.toArray(test.isMaterialChange.extensions),
            files: array_1.toArray(test.isMaterialChange.files),
            globs: getGlobPatterns(test.isMaterialChange),
        });
    }
    return undefined;
};
const HasFileContaining = async (test) => {
    if (!!test.hasFileContaining) {
        if (!test.hasFileContaining.content) {
            throw new Error("Push test 'hasFileContaining' can't be used without 'content' property");
        }
        return commonPushTests_1.hasFileContaining(getGlobPatterns(test.hasFileContaining) || "**/*", typeof test.hasFileContaining.content === "string" ? new RegExp(test.hasFileContaining.content) : test.hasFileContaining.content);
    }
    return undefined;
};
const HasResourceProvider = async (test) => {
    if (!!test.hasResourceProvider) {
        if (!test.hasResourceProvider.type) {
            throw new Error("Push test 'hasResourceProvider' can't be used without 'type' property");
        }
        return commonPushTests_1.hasResourceProvider(test.hasResourceProvider.type, test.hasResourceProvider.name);
    }
    return undefined;
};
const HasCommit = async (test) => {
    if (!!test.hasCommit) {
        return commit_1.hasCommit(typeof test.hasCommit === "string" ? new RegExp(test.hasCommit) : test.hasCommit);
    }
    return undefined;
};
const Not = async (test, additionalTests, extensionTests) => {
    if (!!test.not) {
        return pushTestUtils_1.not(await mapTest(test.not, additionalTests, extensionTests));
    }
    return undefined;
};
const And = async (test, additionalTests, extensionTests) => {
    if (!!test.and) {
        return pushTestUtils_1.and(...array_1.toArray(await mapTests(test.and, additionalTests, extensionTests)));
    }
    return undefined;
};
const Or = async (test, additionalTests, extensionTests) => {
    if (!!test.or) {
        return pushTestUtils_1.or(...array_1.toArray(await mapTests(test.or, additionalTests, extensionTests)));
    }
    return undefined;
};
const AdditionalTest = async (test, additionalTests) => {
    if (!!test.use && !!additionalTests[test.use]) {
        return additionalTests[test.use];
    }
    return undefined;
};
const FunctionTest = async (test) => {
    if (typeof test === "function") {
        return PushTest_1.pushTest(test.toString(), test);
    }
    return undefined;
};
const ExtensionTest = async (test, additionalTests, extensionTests) => {
    for (const extTestName in extensionTests) {
        if (test.use === extTestName) {
            const extTest = await extensionTests[extTestName](test.parameters || {});
            if (!!extTest.name && !!extTest.mapping) {
                return extTest;
            }
            else {
                return PushTest_1.pushTest(extTestName, extTest);
            }
        }
    }
    return undefined;
};
exports.CreatePushTests = [
    HasFile,
    IsRepo,
    IsBranch,
    IsDefaultBranch,
    IsGoal,
    IsSkillConfigured,
    IsMaterialChange,
    HasFileContaining,
    HasResourceProvider,
    HasCommit,
    Not,
    And,
    Or,
    AdditionalTest,
    FunctionTest,
    ExtensionTest,
];
async function mapTest(test, additionalTests, extensionTests) {
    for (const createPushTest of exports.CreatePushTests) {
        const pt = await createPushTest(test, additionalTests, extensionTests);
        if (!!pt) {
            return pt;
        }
    }
    throw new Error(`Unable to construct push test from '${JSON.stringify(test)}'`);
}
exports.mapTest = mapTest;
function getGlobPatterns(test) {
    const pattern = test.globPattern || test.pattern || test.globPatterns || test.patterns;
    return array_1.toArray(pattern);
}
function getStringOrRegexp(toTest) {
    if (!toTest) {
        return undefined;
    }
    else if (typeof toTest === "string") {
        return toTest;
    }
    else if (toTest.regexp !== undefined) {
        return new RegExp(toTest.regexp);
    }
    else {
        return undefined;
    }
}
//# sourceMappingURL=mapPushTests.js.map