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

import com.atlassian.bitbucket.rest.RestErrors;
import com.atlassian.bitbucket.rest.util.ResponseFactory;
import com.atlassian.bitbucket.rest.util.RestUtils;
import com.atlassian.bitbucket.pull.PullRequest;
import com.atlassian.bitbucket.pull.PullRequestService;
import com.atlassian.bitbucket.pull.PullRequestTaskSearchRequest;
import com.atlassian.bitbucket.rest.util.RestPage;
import com.atlassian.bitbucket.rest.task.RestTask;
import com.atlassian.bitbucket.rest.task.RestTaskCount;
import com.atlassian.bitbucket.task.TaskState;
import com.atlassian.bitbucket.task.Task;
import com.atlassian.bitbucket.task.TaskCount;
import com.atlassian.bitbucket.util.Page;
import com.atlassian.bitbucket.util.PageRequest;
import com.sun.jersey.spi.resource.Singleton;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import static com.atlassian.bitbucket.rest.util.ResourcePatterns.PULL_REQUEST_URI;
import static com.atlassian.bitbucket.rest.util.ResourcePatterns.TASK_URI;

@Consumes({MediaType.APPLICATION_JSON})
@Path(PULL_REQUEST_URI + "/" + TASK_URI)
@Produces({RestUtils.APPLICATION_JSON_UTF8})
@Singleton
public class PullRequestTaskResource {

    private final PullRequestService pullRequestService;

    public PullRequestTaskResource(PullRequestService pullRequestService) {
        this.pullRequestService = pullRequestService;
    }

    /**
     * Retrieve the total number of {@link TaskState#OPEN open} and
     * {@link TaskState#RESOLVED resolved} tasks associated with a pull request.
     *
     * @param pullRequest the pull request the tasks are associated with
     *
     * @response.representation.200.mediaType application/json
     * @response.representation.200.qname taskCount
     * @response.representation.200.example {@link RestTaskCount#RESPONSE_GET_TASK_COUNT_EXAMPLE}
     * @response.representation.200.doc Total number of {@link TaskState#OPEN open} and
     * {@link TaskState#RESOLVED resolved} tasks associated with the pull request.
     *
     * @response.representation.401.mediaType application/json
     * @response.representation.401.qname errors
     * @response.representation.401.example {@link RestErrors#EXAMPLE}
     * @response.representation.401.doc If the current user cannot access the pull request
     *
     * @response.representation.404.mediaType application/json
     * @response.representation.404.qname errors
     * @response.representation.404.example {@link RestErrors#EXAMPLE}
     * @response.representation.404.doc If the pull request does not exist
     */
    @GET
    @Path("count")
    public Response countPullRequestTasks(@Context PullRequest pullRequest) {
        TaskCount taskCount = pullRequestService.countTasks(new PullRequestTaskSearchRequest.Builder(pullRequest).build());
        return ResponseFactory.ok()
                .entity(RestTaskCount.REST_TRANSFORM.apply(taskCount))
                .build();
    }

    /**
     * Retrieve the tasks associated with a pull request.
     *
     * @param pullRequest the pull request the tasks are associated with
     * @param pageRequest a page request delimiting the retrieval of the tasks
     *
     * @response.representation.200.mediaType application/json
     * @response.representation.200.qname task
     * @response.representation.200.example {@link RestTask#RESPONSE_GET_PR_TASKS_EXAMPLE}
     * @response.representation.200.doc A page of tasks associated with the pull request.
     *
     * @response.representation.401.mediaType application/json
     * @response.representation.401.qname errors
     * @response.representation.401.example {@link RestErrors#EXAMPLE}
     * @response.representation.401.doc If the current user cannot access the pull request
     *
     * @response.representation.404.mediaType application/json
     * @response.representation.404.qname errors
     * @response.representation.404.example {@link RestErrors#EXAMPLE}
     * @response.representation.404.doc If the pull request does not exist
     */
    @GET
    public Response getPullRequestTasks(@Context PullRequest pullRequest,
                                        @Context final PageRequest pageRequest) {
        Page<Task> page = pullRequestService.searchTasks(new PullRequestTaskSearchRequest.Builder(pullRequest).build(), pageRequest);
        return ResponseFactory
            .ok(new RestPage<>(page, RestTask.REST_TRANSFORM))
            .build();
    }
}
