package com.atlassian.stash.internal.repository;

import com.atlassian.bitbucket.util.Page;
import com.atlassian.bitbucket.util.PageRequest;
import com.atlassian.stash.internal.Dao;
import com.atlassian.stash.internal.commit.InternalCommitDiscussion;
import com.atlassian.stash.internal.commit.InternalCommitDiscussionCommentActivity;
import com.atlassian.stash.internal.pull.InternalPullRequest;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Map;
import java.util.Set;

/**
 * @since 2.11
 */
public interface RepositoryActivityDao extends Dao<Long, InternalRepositoryActivity> {

    /**
     * Searches across comment activities for the specified {@link InternalRepository repository} to map counts by
     * commit IDs. If a requested commit has no comments, it will not be added to the returned map <i>at all</i>.
     * <p>
     * The same commit can be commented on in different repositories. The counts returned here exclude comments in any
     * repository other than the specified one. There is currently no mechanism for searching for comments agnostic of
     * the repository they were made in.
     *
     * @param repositoryId the {@link InternalRepository#getId() repository ID} to search discussions for
     * @param commitIds    a set containing 1 or more {@link InternalCommitDiscussion#getCommitId() commit IDs}
     * @return a map from a commit ID to its comment count <i>for the specified repository</i>
     * @since 2.12
     */
    @Nonnull
    Map<String, Long> countCommentsByCommit(int repositoryId, @Nonnull Set<String> commitIds);

    /**
     * Searches across comment activities for the specified {@link InternalPullRequest pull request} to map counts by
     * commit IDs. If a requested commit has no comments, it will not be added to the returned map <i>at all</i>.
     * <p>
     * The same commit can be commented on in different pull request. The counts returned here exclude comments in any
     * pull request other than the specified one. There is currently no mechanism for searching for pull request
     * commit comments agnostic of the pull request they were made in.
     *
     * @param repositoryId  the {@link InternalRepository#getId() repository ID} to search discussions for
     * @param pullRequestId the {@link InternalPullRequest#getId() pull request ID} to search discussions for
     * @param commitIds     a set containing 1 or more {@link InternalCommitDiscussion#getCommitId() commit IDs}
     * @return a map from a commit ID to its comment count <i>for the specified repository</i>
     * @since 4.8
     */
    @Nonnull
    Map<String, Long> countCommentsByPullRequestCommit(int repositoryId, long pullRequestId, @Nonnull Set<String> commitIds);

    /**
     * Deletes any activities which reference the specified comment. This is necessary to allow the comment to be
     * deleted due to foreign keys in the database.
     *
     * @param commentId the ID of the comment to delete activities for
     * @return the number of activities deleted
     */
    int deleteByComment(long commentId);

    /**
     * Deletes activities for the specified {@link InternalRepository}.
     *
     * @param repositoryId the {@link InternalRepository#getId() ID} for the repository
     * @return the number of activities deleted
     * @since 3.0.7, 3.1.4, 3.2.1
     */
    int deleteByRepository(int repositoryId);

    /**
     * Retrieves the {@link InternalCommitDiscussionCommentActivity} associated with the comment whose ID is supplied.
     * This returns any {@link InternalCommitDiscussionCommentActivity} and does no filtering unlike the find methods
     * in this class.
     *
     * @param commentId the ID of the comment
     * @return the activity associated with the comment or null if one was not found
     */
    @Nullable
    InternalCommitDiscussionCommentActivity findByComment(long commentId);

    /**
     * Retrieves a page of {@link InternalRepositoryActivity activies} for the specified repository. Activities of
     * any type are returned, ordered from most recent to least recent.
     *
     * @param repositoryId the {@link InternalRepository#getId() ID} for the repository
     * @param pageRequest  start index and limit for the page of activities to return
     * @return a page containing zero or more activities for the specified repository, most recent first
     */
    @Nonnull
    Page<InternalRepositoryActivity> findByRepository(int repositoryId, @Nonnull PageRequest pageRequest);
}
