package io.digdag.server.rs;

import com.google.common.base.Optional;
import com.google.inject.Inject;
import io.digdag.client.api.RestSession;
import io.digdag.client.api.RestSessionCollection;
import io.digdag.client.api.RestSessionAttempt;
import io.digdag.client.api.RestSessionAttemptCollection;
import io.digdag.core.database.TransactionManager;
import io.digdag.core.repository.ProjectStore;
import io.digdag.core.repository.ProjectStoreManager;
import io.digdag.core.repository.ResourceNotFoundException;
import io.digdag.core.repository.StoredProject;
import io.digdag.core.session.SessionStore;
import io.digdag.core.session.SessionStoreManager;
import io.digdag.core.session.StoredSession;
import io.digdag.core.session.StoredSessionAttempt;
import io.digdag.core.session.StoredSessionWithLastAttempt;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;

import java.util.List;
import java.util.stream.Collectors;

@Path("/")
@Produces("application/json")
public class SessionResource
        extends AuthenticatedResource
{
    // GET  /api/sessions                                    # List sessions from recent to old
    // GET  /api/sessions/{id}                               # Get a session by id
    // GET  /api/sessions/{id}/attempts                      # List attempts of a session

    private final ProjectStoreManager rm;
    private final SessionStoreManager sm;
    private final TransactionManager tm;

    @Inject
    public SessionResource(
            ProjectStoreManager rm,
            SessionStoreManager sm,
            TransactionManager tm)
    {
        this.rm = rm;
        this.sm = sm;
        this.tm = tm;
    }

    @GET
    @Path("/api/sessions")
    public RestSessionCollection getSessions(@QueryParam("last_id") Long lastId)
    {
        return tm.begin(() -> {
            ProjectStore rs = rm.getProjectStore(getSiteId());
            SessionStore ss = sm.getSessionStore(getSiteId());

            List<StoredSessionWithLastAttempt> sessions = ss.getSessions(100, Optional.fromNullable(lastId));

            return RestModels.sessionCollection(rs, sessions);
        });
    }

    @GET
    @Path("/api/sessions/{id}")
    public RestSession getSession(@PathParam("id") long id)
            throws ResourceNotFoundException
    {
        return tm.begin(() -> {
            StoredSessionWithLastAttempt session = sm.getSessionStore(getSiteId())
                    .getSessionById(id);

            StoredProject proj = rm.getProjectStore(getSiteId())
                    .getProjectById(session.getProjectId());

            return RestModels.session(session, proj.getName());
        }, ResourceNotFoundException.class);
    }

    @GET
    @Path("/api/sessions/{id}/attempts")
    public RestSessionAttemptCollection getSessionAttempts(
            @PathParam("id") long id,
            @QueryParam("last_id") Long lastId)
            throws ResourceNotFoundException
    {
        return tm.begin(() -> {
            ProjectStore rs = rm.getProjectStore(getSiteId());
            SessionStore ss = sm.getSessionStore(getSiteId());

            StoredSession session = ss.getSessionById(id);
            StoredProject project = rs.getProjectById(session.getProjectId());
            List<StoredSessionAttempt> attempts = ss.getAttemptsOfSession(id, 100, Optional.fromNullable(lastId));

            List<RestSessionAttempt> collection = attempts.stream()
                    .map(attempt -> RestModels.attempt(session, attempt, project.getName()))
                    .collect(Collectors.toList());

            return RestModels.attemptCollection(collection);
        }, ResourceNotFoundException.class);
    }
}

@@ -1511,16 +1511,75 @@
 ager tm;
+%0A    private static final int MAX_SESSION_PAGE_SIZE = 1000;
 %0A%0A    @I
@@ -1879,16 +1879,29 @@
 essions(
+%0A            
 @QueryPa
@@ -1926,23 +1926,174 @@
 g lastId
-)%0A    %7B
+,%0A            @QueryParam(%22page_size%22) int pageSize)%0A    %7B%0A        int validPageSize = QueryParamValidator.validatePageSize(pageSize, MAX_SESSION_PAGE_SIZE);%0A
 %0A       
@@ -2317,19 +2317,29 @@
 essions(
-100
+validPageSize
 , Option

Support page_size at GET /api/sessions