"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.assertUniversalGenerator = void 0;
const ActionResult_1 = require("@atomist/automation-client/lib/action/ActionResult");
const string_1 = require("@atomist/automation-client/lib/internal/util/string");
const BuildableAutomationServer_1 = require("@atomist/automation-client/lib/server/BuildableAutomationServer");
const assert = require("assert");
const flatten = require("flat");
const _ = require("lodash");
const AbstractSoftwareDeliveryMachine_1 = require("../../../api-helper/machine/AbstractSoftwareDeliveryMachine");
const handlerRegistrations_1 = require("../../../api-helper/machine/handlerRegistrations");
const defaultSoftwareDeliveryMachineConfiguration_1 = require("../../../core/machine/defaultSoftwareDeliveryMachineConfiguration");
const array_1 = require("../../../core/util/misc/array");
const invokeCommand_1 = require("../../job/invokeCommand");
const generator_1 = require("../generator");
async function assertUniversalGenerator(generatorUnderTest, transformsUnderTest, initialParams, promptForParams = {}) {
    try {
        // Prepare the result of generator run
        let project;
        let id;
        let params;
        // Set up configuration and overwrite the projectPersister to capture the result of the generator
        const configuration = _.merge({}, Object.assign(Object.assign({}, defaultSoftwareDeliveryMachineConfiguration_1.defaultSoftwareDeliveryMachineConfiguration({})), { name: "test" }), {
            sdm: {
                projectPersister: async (p, credentials, targetId, parameters) => {
                    project = p;
                    id = targetId;
                    params = parameters;
                    return ActionResult_1.successOn(p);
                },
            },
        });
        const automationServer = new BuildableAutomationServer_1.BuildableAutomationServer({});
        const sdm = new TestSoftwareDeliveryMachine("test", configuration);
        global.__runningAutomationClient = {
            configuration,
            automationServer,
        };
        // Create the generator instance and register it with the underlying automation client
        const generator = generator_1.universalGenerator(sdm, generatorUnderTest, array_1.toArray(transformsUnderTest));
        automationServer.registerCommandHandler(handlerRegistrations_1.generatorRegistrationToCommand(sdm, generator));
        let parameterSpecs = [];
        const messageClient = {
            respond: async (msg) => {
                if (!!msg.parameter_specs) {
                    parameterSpecs = msg.parameter_specs;
                }
            },
            send: async () => {
            },
            delete: async () => {
            },
        };
        // Invoke the generator with the initial set of parameters
        let result = await invokeCommand_1.invokeCommand(generatorUnderTest, initialParams, mockHandlerContext(messageClient, initialParams));
        assert.deepStrictEqual(result.code, 0, `Generator failed during initial execution: ${result.message}`);
        const keys = _.keys(promptForParams).sort();
        assert.deepStrictEqual(parameterSpecs.map(p => p.name).some(n => !keys.includes(n)), false, `Some expected parameters not provided: ${parameterSpecs.map(p => p.name).join(", ")}`);
        if (!!project) {
            return {
                id,
                project,
                parameters: params,
            };
        }
        // Now invoke generator with additional parameters needed by the matched transformsAndParameters
        const allParameters = Object.assign(Object.assign({}, initialParams), promptForParams);
        result = await invokeCommand_1.invokeCommand(generatorUnderTest, allParameters, mockHandlerContext(messageClient, allParameters));
        assert.deepStrictEqual(result.code, 0, `Generator failed during parameter prompt execution: ${result.message}`);
        assert(!!project, "Generated project is undefined");
        return {
            id,
            project,
            parameters: params,
        };
    }
    finally {
        delete global.__runningAutomationClient;
    }
}
exports.assertUniversalGenerator = assertUniversalGenerator;
function mockHandlerContext(messageClient, params) {
    return {
        messageClient,
        trigger: {
            parameters: flattenParameters(params),
        },
        invocationId: string_1.guid(),
        correlationId: string_1.guid(),
        graphClient: undefined,
        workspaceId: `A${string_1.guid().slice(0, 7).toUpperCase()}`,
    };
}
function flattenParameters(params) {
    const parameters = [];
    _.forEach(flatten(params), (v, k) => {
        parameters.push({ name: k, value: v });
    });
    return parameters;
}
class TestSoftwareDeliveryMachine extends AbstractSoftwareDeliveryMachine_1.AbstractSoftwareDeliveryMachine {
    constructor(name, configuration) {
        super(name, configuration, []);
        this.commandHandlers = [];
        this.eventHandlers = [];
        this.ingesters = [];
    }
}
//# sourceMappingURL=assertGenerator.js.map