package com.atlassian.bitbucket.repository;

import com.atlassian.bitbucket.project.Project;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

/**
 * Allows retrieving {@link Repository repositories} by their {@link Repository#getId() ID} or
 * {@link Repository#getProject() project} and {@link Repository#getSlug() slug}.
 * <p>
 * This is a simplification of the {@link RepositoryService}, intended to be used in cases where a component needs to
 * be able to look up repositories but doesn't need the full service functionality. Using this interface instead makes
 * such components easier to test.
 * <p>
 * <b>Plugin developers</b>: Plugins cannot autowire their components when importing both {@code RepositorySupplier} and
 * {@link RepositoryService}. In general, if a plugin needs {@link RepositoryService} methods, it should <i>only</i>
 * use the {@link RepositoryService}. This interface should be used when a plugin only needs to retrieve repositories.
 */
public interface RepositorySupplier {

    /**
     * Retrieves a {@link Repository} by its {@link Repository#getId() ID}.
     *
     * @param id the repository's ID
     * @return the request repository, or {@code null} if there is no repository with the specified ID or the current
     *         user does not have access to it
     */
    @Nullable
    Repository getById(int id);

    /**
     * Retrieves a {@link Repository} by its {@link Repository#getSlug() slug}. Slugs are only unique within a given
     * {@link Project}, so the {@link Project#getKey() project key} is also required.
     *
     * @param projectKey the {@link Project#getKey() key} of the project to search in
     * @param slug       the {@link Repository#getSlug() slug} of the repository to search for
     * @return the repository, or {@code null} if no project matches the specified slug within the specified project
     */
    @Nullable
    Repository getBySlug(@Nonnull String projectKey, @Nonnull String slug);

    /**
     * Retrieves a {@link Repository} by its {@link Repository#getSlug() slug}. Slugs are only unique within a given
     * {@link Project}, so the {@link Project#getKey() project key} and {@link Project#getNamespace() project namespace}
     * are required. Unless in {@link com.atlassian.bitbucket.server.ApplicationMode#MIRROR mirror mode} the namespace
     * specified should always be {@code null}.
     *
     * @param projectNamespace the {@link Project#getNamespace() namespace} of the project to search in, {@code null}
     *                         unless in {@link com.atlassian.bitbucket.server.ApplicationMode#MIRROR mirror mode}
     * @param projectKey the {@link Project#getKey() key} of the project to search in
     * @param slug       the {@link Repository#getSlug() slug} of the repository to search for
     * @return the repository, or {@code null} if no project matches the specified slug within the specified project
     * @since 4.6
     */
    @Nullable
    Repository getBySlug(@Nullable String projectNamespace, @Nonnull String projectKey, @Nonnull String slug);
}
