"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.ProjectListenerInvokingProjectLoader = void 0;
const HandlerResult_1 = require("@atomist/automation-client/lib/HandlerResult");
const skillContext_1 = require("../../api/context/skillContext");
const GoalInvocation_1 = require("../../api/goal/GoalInvocation");
const commonPushTests_1 = require("../../api/mapping/support/commonPushTests");
const storeGoals_1 = require("../goal/storeGoals");
const result_1 = require("../misc/result");
/**
 * ProjectLoader implementation that invokes GoalProjectListener instances on the loaded project.
 * Can be used to restore state into a project/workspace area.
 */
class ProjectListenerInvokingProjectLoader {
    constructor(gi, listeners) {
        this.gi = gi;
        this.listeners = listeners;
    }
    async doWithProject(params, action) {
        return this.gi.configuration.sdm.projectLoader.doWithProject(params, async (p) => {
            let result;
            try {
                // invoke the before listeners
                const beforeResult = await this.invokeListeners(p, GoalInvocation_1.GoalProjectListenerEvent.before);
                updateGoalProperties(this.gi.goalEvent, beforeResult);
                if (!!beforeResult && beforeResult.code !== 0) {
                    return beforeResult;
                }
                // invoke the wrapped action
                result = await action(p);
            }
            catch (err) {
                throw err;
            }
            finally {
                // invoke the after listeners
                const afterResult = await this.invokeListeners(p, GoalInvocation_1.GoalProjectListenerEvent.after);
                updateGoalProperties(this.gi.goalEvent, afterResult);
                if (!!afterResult && afterResult.code !== 0) {
                    result = afterResult;
                }
            }
            return result;
        });
    }
    async invokeListeners(p, event) {
        const pli = {
            addressChannels: this.gi.addressChannels,
            preferences: this.gi.preferences,
            configuration: this.gi.configuration,
            context: this.gi.context,
            credentials: this.gi.credentials,
            id: this.gi.id,
            project: p,
            push: this.gi.goalEvent.push,
            skill: skillContext_1.createSkillContext(this.gi.context),
        };
        for (const lr of this.listeners) {
            const pushTest = lr.pushTest || commonPushTests_1.AnyPush;
            const events = lr.events || [GoalInvocation_1.GoalProjectListenerEvent.before, GoalInvocation_1.GoalProjectListenerEvent.after];
            if (events.includes(event) && await pushTest.mapping(pli)) {
                this.gi.progressLog.write("/--");
                this.gi.progressLog.write(`Invoking ${event} project listener: ${lr.name}`);
                await storeGoals_1.updateGoal(this.gi.context, this.gi.goalEvent, {
                    state: this.gi.goalEvent.state,
                    phase: lr.name,
                    description: this.gi.goalEvent.description,
                    url: this.gi.goalEvent.url,
                });
                const postResult = await lr.listener(p, this.gi, event);
                updateGoalProperties(this.gi.goalEvent, postResult);
                this.gi.progressLog.write(`Result: ${postResult ? result_1.serializeResult(postResult) : "Success"}`);
                this.gi.progressLog.write("\\--");
                if (!!postResult && postResult.code !== 0) {
                    return postResult;
                }
            }
        }
        return HandlerResult_1.Success;
    }
}
exports.ProjectListenerInvokingProjectLoader = ProjectListenerInvokingProjectLoader;
function updateGoalProperties(goalEvent, result) {
    if (!!result) {
        goalEvent.description = !!result.description ? result.description : goalEvent.description;
        goalEvent.data = !!result.data ? result.data : goalEvent.data;
        goalEvent.externalUrls = !!result.externalUrls ? result.externalUrls : goalEvent.externalUrls;
        goalEvent.phase = !!result.phase ? result.phase : goalEvent.phase;
    }
}
//# sourceMappingURL=ProjectListenerInvokingProjectLoader.js.map