"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.DefaultGoalImplementationMapper = void 0;
const configuration_1 = require("@atomist/automation-client/lib/configuration");
const commonPushTests_1 = require("../../api/mapping/support/commonPushTests");
/**
 * Concrete implementation of GoalImplementationMapper
 */
class DefaultGoalImplementationMapper {
    constructor() {
        this.implementations = [];
        this.sideEffects = [];
        this.callbacks = [];
        this.goals = [];
    }
    hasImplementation() {
        return this.goals.filter(g => g.uniqueName !== "nevermind").length > 0;
    }
    findImplementationBySdmGoal(goal) {
        let matchedNames = this.implementations.filter(m => m.implementationName === goal.fulfillment.name &&
            m.goal.uniqueName === uniqueName(goal));
        if (matchedNames.length > 1) {
            throw new Error(`Multiple implementations found for name '${goal.fulfillment.name}' on goal '${goal.uniqueName}'`);
        }
        if (matchedNames.length === 0) {
            matchedNames = this.implementations.filter(m => m.goal.name === goal.fulfillment.name);
            if (matchedNames.length > 1) {
                throw new Error(`Multiple implementations found for name '${goal.fulfillment.name}' on goal '${goal.name}'`);
            }
            if (matchedNames.length === 0) {
                throw new Error(`No implementation found with name '${goal.fulfillment.name}': ` +
                    `Found ${this.implementations.map(impl => impl.implementationName)}`);
            }
        }
        return matchedNames[0];
    }
    addImplementation(implementation) {
        if (this.implementations.some(i => i.implementationName === implementation.implementationName &&
            i.goal.uniqueName === implementation.goal.uniqueName &&
            i.goal.environment === implementation.goal.environment)) {
            throw new Error(`Implementation with name '${implementation.implementationName}' already registered for goal '${implementation.goal.name}'`);
        }
        this.addGoal(implementation.goal);
        this.implementations.push(implementation);
        return this;
    }
    addSideEffect(sideEffect) {
        sideEffect.pushTest = sideEffect.pushTest || commonPushTests_1.AnyPush;
        sideEffect.registration = sideEffect.registration || configuration_1.configurationValue("name");
        this.addGoal(sideEffect.goal);
        this.sideEffects.push(sideEffect);
        return this;
    }
    addFulfillmentCallback(callback) {
        this.callbacks.push(callback);
        return this;
    }
    async findFulfillmentByPush(goal, inv) {
        const implementationsForGoal = this.implementations.filter(m => m.goal.uniqueName === uniqueName(goal) &&
            m.goal.environment === goal.environment);
        const matchingFulfillments = [];
        for (const implementation of implementationsForGoal) {
            if (await implementation.pushTest.mapping(inv)) {
                matchingFulfillments.push(implementation);
            }
        }
        if (matchingFulfillments.length > 1) {
            throw new Error(`Multiple matching implementations for goal '${goal.uniqueName}' found: '${matchingFulfillments.map(f => f.implementationName).join(", ")}'`);
        }
        else if (matchingFulfillments.length === 1) {
            return matchingFulfillments[0];
        }
        const knownSideEffects = this.sideEffects.filter(m => m.goal.uniqueName === uniqueName(goal) &&
            m.goal.environment === goal.environment);
        for (const sideEffect of knownSideEffects) {
            if (await sideEffect.pushTest.mapping(inv)) {
                return sideEffect;
            }
        }
        return undefined;
    }
    findFulfillmentCallbackForGoal(sdmGoal) {
        return this.callbacks.filter(c => c.goal.uniqueName === uniqueName(sdmGoal) &&
            // This slice is required because environment is suffixed with /
            (c.goal.definition.environment.slice(0, -1) === sdmGoal.environment
                || c.goal.definition.environment === sdmGoal.environment));
    }
    findGoalBySdmGoal(sdmGoal) {
        return this.goals.find(g => g.uniqueName === uniqueName(sdmGoal) &&
            // This slice is required because environment is suffixed with /
            (g.definition.environment.slice(0, -1) === g.environment
                || g.definition.environment === g.environment));
    }
    addGoal(goal) {
        const existingGoal = this.goals.find(g => g.uniqueName === goal.uniqueName);
        if (!existingGoal) {
            this.goals.push(goal);
        }
        else if (existingGoal !== goal) {
            throw new Error(`Goal with uniqueName '${goal.uniqueName}' already registered`);
        }
    }
}
exports.DefaultGoalImplementationMapper = DefaultGoalImplementationMapper;
function uniqueName(goal) {
    const un = goal.uniqueName.split("#sdm:");
    return un[0];
}
//# sourceMappingURL=DefaultGoalImplementationMapper.js.map