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 javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.function.Predicate;

public interface RepositoryDao extends Dao<Integer, InternalRepository> {

    /**
     * Returns the number of repositories in this installation.
     *
     * @return the number of repositories in this installation
     * @since 3.7
     */
    long countAll();

    long countByHierarchy(String hierarchyId);

    long countByProject(int projectId);

    /**
     * @since 2.5
     */
    long countPublicByProject(int projectId);

    @Nonnull
    Page<InternalRepository> findByHierarchy(@Nonnull InternalRepository repository, @Nonnull PageRequest pageRequest,
                                             @Nonnull Predicate<? super InternalRepository> predicate);

    @Nonnull
    Page<InternalRepository> findByOrigin(@Nonnull InternalRepository origin, @Nonnull PageRequest pageRequest,
                                          @Nonnull Predicate<? super InternalRepository> predicate);

    @Nullable
    InternalRepository findByOriginInProject(@Nonnull InternalRepository origin, int projectId);

    @Nonnull
    Page<InternalRepository> findByOwner(int ownerId, @Nonnull PageRequest pageRequest,
                                         @Nonnull Predicate<? super InternalRepository> predicate);

    @Nonnull
    Page<InternalRepository> findByProjectKey(@Nullable String projectNamespace, @Nonnull String projectKey,
                                              @Nonnull PageRequest pageRequest,
                                              @Nonnull Predicate<? super InternalRepository> predicate);

    @Nullable
    InternalRepository getBySlug(@Nullable String projectNamespace, @Nonnull String projectKey, @Nonnull String slug);

    @Nonnull
    Iterable<Integer> getForkIds(@Nonnull InternalRepository repository);

    /**
     * Retrieves a page of repository IDs for {@link InternalRepository repositories} which are in the provided
     * {@link com.atlassian.bitbucket.repository.Repository.State state(s)}.
     *
     * @param pageRequest describes the page of repositories IDs to be returned
     * @param state       describes the {@link com.atlassian.bitbucket.repository.Repository.State state} of the repositories to retrieve,
     *                    if not specified {@link com.atlassian.bitbucket.repository.Repository.State#AVAILABLE Available} is used.
     * @return a {@link Page} containing repository IDs
     * @since 4.8
     */
    @Nonnull
    Page<Integer> getIds(@Nonnull PageRequest pageRequest, InternalRepository.State... state);

    /**
     * Retrieves a page of {@link InternalRepository repositories} that match the provided
     * {@link RepositorySearchCriteria criteria}, additionally filtered by the provided {@code Predicate}.
     *
     * @param searchCriteria describes the repositories that should be returned
     * @param pageRequest    describes the page of repositories to be returned
     * @param predicate      the predicate to use to filter results, useful for applying permission checks
     * @return a page containing 0 or more matching repositories
     */
    @Nonnull
    Page<InternalRepository> search(@Nonnull RepositorySearchCriteria searchCriteria, @Nonnull PageRequest pageRequest,
                                    @Nonnull Predicate<? super InternalRepository> predicate);

    int updateOrigin(@Nonnull InternalRepository oldOrigin, @Nullable InternalRepository newOrigin);
}
