package com.atlassian.bitbucket.scm.pull;

import com.atlassian.bitbucket.commit.CommitCallback;
import com.atlassian.bitbucket.content.ChangeCallback;
import com.atlassian.bitbucket.content.DiffContentCallback;
import com.atlassian.bitbucket.pull.PullRequest;
import com.atlassian.bitbucket.repository.Branch;
import com.atlassian.bitbucket.scm.Command;

import javax.annotation.Nonnull;

public interface PluginPullRequestCommandFactory {

    /**
     * @param parameters describes the repository and providies a context for the command to use to retrieve
     *                   affected rescopes and apply updates
     * @return a command which, when called, will analyse any rescopes from the provided context
     * @since 4.5
     */
    @Nonnull
    default Command<Void> bulkRescope(@Nonnull BulkRescopeCommandParameters parameters) {
        throw new UnsupportedOperationException(parameters.getRepository().getScmId() +
                " does not support bulk rescope (yet)");
    }

    @Nonnull
    Command<Boolean> canMerge(@Nonnull PullRequest pullRequest);

    @Nonnull
    Command<Void> changes(@Nonnull PullRequest pullRequest, @Nonnull PullRequestChangeCommandParameters parameters,
                          @Nonnull ChangeCallback callback);

    /**
     * @param pullRequest describes the refs being compared
     * @param callback    a callback to receive commits which are unique to the {@link PullRequest#getFromRef from ref}
     * @return a command which, when executed, will stream commits referenced by the {@link PullRequest#getFromRef from
     *         ref} which are not referenced by the {@link PullRequest#getToRef to ref}
     */
    @Nonnull
    Command<Void> commits(@Nonnull PullRequest pullRequest, @Nonnull CommitCallback callback);

    @Nonnull
    Command<Void> diff(@Nonnull PullRequest pullRequest, @Nonnull PullRequestDiffCommandParameters parameters,
                       @Nonnull DiffContentCallback callback);

    @Nonnull
    Command<PullRequestEffectiveDiff> effectiveDiff(@Nonnull PullRequest pullRequest);

    @Nonnull
    Command<Branch> merge(@Nonnull PullRequest pullRequest, @Nonnull PullRequestMergeCommandParameters parameters);

    /**
     * @param parameters describes the repository and ref changes, as well as providing a context for the
     *                   command to use to retrieve affected pull requests and apply updates
     * @return a command which, when called, will rescope any pull requests affected by ref changes in the
     *         specified repository
     * @deprecated since 4.5, to be removed in 5.0. SCMs should implement
     *             {@link #bulkRescope(BulkRescopeCommandParameters)} instead. SCMs that implement bulkRescope do not
     *             have to implement this method anymore.
     */
    @Deprecated
    @Nonnull
    default Command<Void> rescope(@Nonnull RepositoryRescopeCommandParameters parameters) {
        throw new UnsupportedOperationException(parameters.getRepository().getScmId() +
                " has migrated to supporting bulkRescope instead");
    }
}
