"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.chattyDryRunAwareEditor = void 0;
const string_1 = require("@atomist/automation-client/lib/internal/util/string");
const projectEditor_1 = require("@atomist/automation-client/lib/operations/edit/projectEditor");
const LocalProject_1 = require("@atomist/automation-client/lib/project/local/LocalProject");
const MessageClient_1 = require("@atomist/automation-client/lib/spi/message/MessageClient");
const logger_1 = require("@atomist/automation-client/lib/util/logger");
const slack_messages_1 = require("@atomist/slack-messages");
const handlerRegistrations_1 = require("../../machine/handlerRegistrations");
const child_process_1 = require("../../misc/child_process");
const messages_1 = require("../../misc/slack/messages");
const confirmEditedness_1 = require("./confirmEditedness");
/**
 * Wrap this editor to make it chatty, so it responds to Slack if there's nothing to do.
 * It also honors the dryRun parameter flag to just capture the git diff and send it back to Slack instead
 * of pushing changes to Git.
 */
function chattyDryRunAwareEditor(ctr, underlyingEditor) {
    return async (project, context, params) => {
        const id = project.id;
        const editorName = ctr.name;
        try {
            await sendDryRunUpdateMessage(editorName, id, params, context, ctr);
            const tentativeEditResult = await projectEditor_1.toEditor(underlyingEditor)(project, context, params);
            const editResult = await confirmEditedness_1.confirmEditedness(tentativeEditResult);
            // Figure out if this CodeTransform is running in dryRun mode; if so capture git diff and don't push changes
            if (!editResult.edited) {
                if (!editResult.success) {
                    await sendFailureMessage(editorName, id, params, editResult, context, ctr);
                }
                else {
                    await sendNoUpdateMessage(editorName, id, params, context, ctr);
                }
                return { target: project, edited: false, success: false };
            }
            else if (isDryRun(params)) {
                if (!LocalProject_1.isLocalProject(project)) {
                    const message = `Project is not a local project, cannot diff`;
                    logger_1.logger.warn(message);
                    return { target: project, edited: false, success: true };
                }
                let diff = "";
                try {
                    const gitDiffResult = await child_process_1.execPromise("git", ["diff"], { cwd: project.baseDir });
                    diff = gitDiffResult.stdout;
                }
                catch (err) {
                    logger_1.logger.error(`Error diffing project: %s`, err.message);
                    diff = `Error obtaining \`git diff\`:\n\n${slack_messages_1.codeBlock(err.message)}`;
                }
                await sendDryRunSummaryMessage(editorName, id, diff, params, context, ctr);
                return { target: project, edited: false, success: true };
            }
            else {
                await sendSuccessMessage(editorName, id, params, context, ctr);
            }
            return editResult;
        }
        catch (err) {
            await context.messageClient.respond(messages_1.slackErrorMessage(`Code Transform${isDryRun(params) ? " (dry run)" : ""}`, `Code transform ${slack_messages_1.italic(editorName)} failed while changing ${slack_messages_1.bold(slug(id))}:\n\n${slack_messages_1.codeBlock(err.message)}`, context), { id: params[handlerRegistrations_1.MsgIdParameter.name] });
            logger_1.logger.warn("Code Transform error acting on %j: %s", project.id, err);
            return { target: project, edited: false, success: false };
        }
    };
}
exports.chattyDryRunAwareEditor = chattyDryRunAwareEditor;
function isDryRun(params) {
    return !!params && params[handlerRegistrations_1.DryRunParameter.name] === true;
}
function slug(id) {
    return `${id.owner}/${id.repo}/${id.branch}`;
}
function isChatty(ctr) {
    if (ctr.chatty !== undefined) {
        return ctr.chatty;
    }
    else {
        return true;
    }
}
async function sendDryRunUpdateMessage(codeTransformName, id, params, ctx, ctr) {
    if (isChatty(ctr) && !!params[handlerRegistrations_1.MsgIdParameter.name]) {
        await ctx.messageClient.respond(messages_1.slackInfoMessage("Code Transform", `Applying code transform ${slack_messages_1.italic(codeTransformName)} to ${slack_messages_1.bold(slug(id))}`), { id: params[handlerRegistrations_1.MsgIdParameter.name] });
    }
}
async function sendFailureMessage(codeTransformName, id, params, editResult, ctx, ctr) {
    if (isChatty(ctr)) {
        await ctx.messageClient.respond(messages_1.slackErrorMessage(`Code Transform${isDryRun(params) ? " (dry run)" : ""}`, `Code transform ${slack_messages_1.italic(codeTransformName)} failed while changing ${slack_messages_1.bold(slug(id))}:\n\n${editResult.error ? slack_messages_1.codeBlock(editResult.error.message) : ""}`, ctx), { id: params[handlerRegistrations_1.MsgIdParameter.name] });
    }
}
async function sendNoUpdateMessage(codeTransformName, id, params, ctx, ctr) {
    if (isChatty(ctr)) {
        await ctx.messageClient.respond(messages_1.slackInfoMessage(`Code Transform${isDryRun(params) ? " (dry run)" : ""}`, `Code transform ${slack_messages_1.italic(codeTransformName)} made no changes to ${slack_messages_1.bold(slug(id))}`), { id: params[handlerRegistrations_1.MsgIdParameter.name] });
    }
}
async function sendSuccessMessage(codeTransformName, id, params, ctx, ctr) {
    if (isChatty(ctr)) {
        const msgId = params[handlerRegistrations_1.MsgIdParameter.name];
        await ctx.messageClient.respond(messages_1.slackSuccessMessage("Code Transform", `Successfully applied code transform ${slack_messages_1.italic(codeTransformName)} to ${slack_messages_1.bold(slug(id))}`), { id: msgId });
    }
}
async function sendDryRunSummaryMessage(codeTransformName, id, diff, params, ctx, ctr) {
    const msgId = params[handlerRegistrations_1.MsgIdParameter.name] || string_1.guid();
    const applyAction = {
        actions: [
            MessageClient_1.buttonForCommand({ text: "Apply Transform" }, codeTransformName, Object.assign(Object.assign({}, params), { "dry-run": false, "msgId": msgId, "targets.sha": params.targets.sha, "targets.owner": id.owner, "targets.repo": id.repo })),
        ],
    };
    await ctx.messageClient.respond(messages_1.slackInfoMessage(`Code Transform (dry run)`, `Code transform ${slack_messages_1.italic(codeTransformName)} would make the following changes to ${slack_messages_1.bold(slug(id))}:
${slack_messages_1.codeBlock(diff)}
`, applyAction), { id: msgId });
}
//# sourceMappingURL=chattyDryRunAwareEditor.js.map