package com.atlassian.bitbucket.project;

import com.atlassian.bitbucket.AuthorisationException;

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

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

    /**
     * Retrieve a {@link Project} by its {@link Project#getId() ID}.
     *
     * @param id the {@link Project#getId() ID} of the project to retrieve
     * @return the project instance or {@code null} if no such project exists
     * @throws AuthorisationException if the current user does not have permission to
     *         access the requested project
     */
    @Nullable
    Project getById(int id);

    /**
     * Retrieves a {@link Project} by its {@link Project#getKey() key}.
     *
     * @param key the {@link Project#getKey() key} of the project to retrieve
     * @return the keyed project, or {@code null} if the key does not match an existing project
     * @throws AuthorisationException if the current user does not have permission to
     *         access the requested project
     */
    @Nullable
    Project getByKey(@Nonnull String key);

    /**
     * Retrieves a {@link Project} by its {@link Project#getNamespace() namespace} and {@link Project#getKey() key}.
     *
     * @param namespace the {@link Project#getNamespace() namespace} of the project to retrieve
     * @param key the {@link Project#getKey() key} of the project to retrieve
     * @return the keyed project, or {@code null} if the key does not match an existing project
     * @throws AuthorisationException if the current user does not have permission to
     *         access the requested project
     *
     * @since 4.3
     */
    @Nullable
    Project getByKey(@Nullable String namespace, @Nonnull String key);

    /**
     * Retrieves a {@link Project} by its {@link Project#getName() name}.
     *
     * @param name the {@link Project#getName() name} of the project to retrieve
     * @return the named project, or {@code null} if the name does not match an existing project
     * @throws AuthorisationException if the current user does not have permission to
     *         access the requested project
     */
    @Nullable
    Project getByName(@Nonnull String name);


    /**
     * Retrieves a {@link Project} by its {@link Project#getNamespace() namespace} and {@link Project#getName() name}.
     *
     * @param namespace the {@link Project#getNamespace() namespace} of the project to retrieve
     * @param name the {@link Project#getName() name} of the project to retrieve
     * @return the named project, or {@code null} if the key does not match an existing project
     * @throws AuthorisationException if the current user does not have permission to
     *         access the requested project
     *
     * @since 4.6
     */
    @Nullable
    Project getByName(@Nullable String namespace, @Nonnull String name);
}
