package com.atlassian.stash.internal.user;

import com.atlassian.bitbucket.util.Page;
import com.atlassian.bitbucket.util.PageRequest;
import com.atlassian.stash.internal.Dao;
import com.atlassian.stash.internal.repository.InternalRepository;

import javax.annotation.Nonnull;
import java.util.function.Predicate;

public interface RepositoryAccessDao extends Dao<InternalRepositoryAccess.PK, InternalRepositoryAccess> {

    /**
     * Deletes all InternalRepositoryAccess entities for the supplied repository.
     *
     * @param repositoryId the repository
     */
    int deleteAllAccessesForRepository(int repositoryId);

    /**
     * Deletes all InternalRepositoryAccess entities for the supplied user.
     *
     * @param userId the user
     */
    int deleteAllAccessesForUser(int userId);

    /**
     * Returns a page of the most recently accessed repositories for a user, in descending order (based on access time).
     *
     * @param userId the user whose repository accesses are to be queried
     * @param pageRequest the page request
     * @param predicate the predicate used to filter the which entities are returned (e.g. to only return entities related to repositories visible by the user).
     *                  If no predicate is supplied no repo accesses are filtered out
     * @return a page of results
     */
    Page<InternalRepository> findRecentRepositories(int userId, @Nonnull PageRequest pageRequest,
                                                    @Nonnull Predicate<? super InternalRepository> predicate);

    /**
     * Attempts to deletes all but the first page of InternalRepositoryAccess entities for the given user
     * (the page size is determined by pageLimit). The query is sorted on lastAccessed descending order.
     *
     * The supplied predicate is used when determining the first page.
     *
     * It's possible that more than pageLimit entities remain after the method returns if, for instance,
     * the final entity in the page shares a lastAccessed date with the first entities in the next page.
     *
     * This method is used to ensure that Stash does not keep an ever-expanding list of the accesses
     * (since Stash only displays a small number of the most recent accesses)
     *
     * @param userId the user whose accesses are to be deleted
     * @param pageLimit the minimum number of entities to retain
     * @param predicate the predicate used to filter the initial list which is used as the cut-off point for deletion
     */
    void trimRecentRepositories(int userId, int pageLimit, @Nonnull Predicate<InternalRepositoryAccess> predicate);
}
