package com.atlassian.stash.internal.notification.pull.handlers;

import com.atlassian.stash.internal.notification.handlers.NotificationHelper;
import com.atlassian.bitbucket.notification.pull.PullRequestFromRefRescopedNotification;
import com.atlassian.bitbucket.user.ApplicationUser;
import com.atlassian.bitbucket.util.Page;

import java.util.Map;

import static com.atlassian.stash.internal.notification.pull.handlers.PullRequestNotificationHelper.COMMITS_KEY;
import static com.atlassian.stash.internal.notification.pull.handlers.PullRequestNotificationHelper.THROTTLED;

/**
 * Handles a pull request rescope notification.
 * <p>
 * Note that the rescope information (i.e. the added and removed commits) is asynchronously computed by Stash;
 * hence the added and removed commits have to be manually determined to add the information to any (immediate)
 * notification.
 */
public class PullRequestFromRefRescopedNotificationHandler
        extends AbstractPullRequestNotificationHandler<PullRequestFromRefRescopedNotification> {

    public static final int MAX_COMMITS_ON_RESCOPE = 5;

    private static final String TEMPLATE = "bitbucket.internal.notification.email.pullRequest.pushed";

    private final PullRequestNotificationHelper notificationHelper;

    public PullRequestFromRefRescopedNotificationHandler(NotificationHelper helper, PullRequestNotificationHelper notificationHelper) {
        super(helper, TEMPLATE);
        this.notificationHelper = notificationHelper;
    }

    @Override
    protected void renderAndDispatch(PullRequestFromRefRescopedNotification notification, Map<String, Object> context, Iterable<ApplicationUser> recipients) {
        // send the notification only if the rescope leads to commits added to the PR
        if (hasNewCommits(context)) {
            super.renderAndDispatch(notification, context, recipients);
        }
    }

    @Override
    protected Map<String, Object> getContext(PullRequestFromRefRescopedNotification notification) {
        Map<String, Object> context = super.getContext(notification);
        context.put(COMMITS_KEY, notificationHelper.getNewCommits(notification.getPullRequest(),
                notification.getPreviousFromHash(), MAX_COMMITS_ON_RESCOPE));
        return context;
    }

    protected static boolean hasNewCommits(Map<String, Object> context) {
        Page commits = (Page) context.get(COMMITS_KEY);
        // if the added commits could not be retrieved because the call was throttled, send the notification anyway
        return commits == THROTTLED || commits.getSize() > 0;
    }
}
