package com.atlassian.stash.internal.rest.pull;

import com.atlassian.bitbucket.rest.enrich.AvatarEnricher;
import com.atlassian.bitbucket.rest.RestErrors;
import com.atlassian.bitbucket.rest.util.*;
import com.atlassian.plugins.rest.common.security.AnonymousAllowed;
import com.atlassian.bitbucket.i18n.I18nService;
import com.atlassian.bitbucket.pull.PullRequestService;
import com.atlassian.bitbucket.repository.Repository;
import com.atlassian.bitbucket.rest.commit.RestCommit;
import com.atlassian.bitbucket.util.PageRequest;
import com.sun.jersey.spi.container.ContainerRequest;
import com.sun.jersey.spi.resource.Singleton;

import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.IOException;

@AnonymousAllowed
@Consumes(MediaType.APPLICATION_JSON)
@Path(ResourcePatterns.PULL_REQUEST_URI + "/commits")
@Produces(RestUtils.APPLICATION_JSON_UTF8)
@Singleton
public class PullRequestCommitResource extends AbstractPullRequestResource {

    private final AvatarEnricher avatarEnricher;

    public PullRequestCommitResource(I18nService i18nService, PullRequestService pullRequestService,
                                     AvatarEnricher avatarEnricher) {
        super(i18nService, pullRequestService);

        this.avatarEnricher = avatarEnricher;
    }

    /**
     * Retrieve commits for the specified pull request.
     * <p>
     * The authenticated user must have <strong>REPO_READ</strong> permission for the repository that this pull request
     * targets to call this resource.
     *
     * @param avatarSize   if present the service adds avatar URLs for commit authors. Should be an integer
     *                     specifying the desired size in pixels. If the parameter is not present, avatar URLs
     *                     will not be set
     * @param avatarScheme the desired scheme for the avatar URL. If the parameter is not present URLs will use
     *                     the same scheme as this request
     * @param withCounts   if set to true, the service will add "authorCount" and "totalCount" at the end of the page.
     *                     "authorCount" is the number of different authors and "totalCount" is the total number of commits.
     *
     * @response.representation.200.mediaType application/json
     * @response.representation.200.qname page
     * @response.representation.200.example {@link RestCommit#PAGE_EXAMPLE}
     * @response.representation.200.doc a page of commits from the supplied pull request.
     *
     * @response.representation.401.mediaType application/json
     * @response.representation.401.qname errors
     * @response.representation.401.example {@link RestErrors#EXAMPLE}
     * @response.representation.401.doc The currently authenticated user has insufficient permissions to view the
     *                                  repository or pull request.
     *
     * @response.representation.404.mediaType application/json
     * @response.representation.404.qname errors
     * @response.representation.404.example {@link RestErrors#EXAMPLE}
     * @response.representation.404.doc The repository or pull request does not exist.
     */
    @GET
    public Response getCommits(@Context final Repository repository,
                               @PathParam(ResourcePatterns.PULL_REQUEST_ID) final long pullRequestId,
                               @QueryParam("withCounts") final boolean withCounts,
                               @Context final PageRequest pageRequest,
                               @Context final ContainerRequest request) {
        return ResponseFactory.ok(
                new JsonStreamingOutput() {

                    @Override
                    public void write(StatefulJsonWriter writer) throws IOException, WebApplicationException {
                        JsonCommitCallback callback = new JsonCommitCallback(writer,
                                RestCommit.createTransformer(request, avatarEnricher),
                                withCounts, pageRequest);

                        pullRequestService.streamCommits(repository.getId(), pullRequestId, callback);
                    }
                }).build();
    }
}
