package com.atlassian.bitbucket.internal.mirroring.mirror.client;

import com.atlassian.bitbucket.internal.mirroring.mirror.ExternalRepository;
import com.atlassian.bitbucket.internal.mirroring.mirror.UpstreamServerRequestFailedException;
import com.atlassian.bitbucket.mirroring.mirror.UpstreamServer;
import com.atlassian.bitbucket.mirroring.mirror.UpstreamServerType;
import com.atlassian.bitbucket.mirroring.mirror.client.UpstreamClient;
import com.atlassian.util.concurrent.Promise;

import javax.annotation.Nonnull;
import java.util.stream.Stream;

/**
 * Client for making calls to an upstream server (master) from a mirror server
 */
public interface InternalUpstreamClient extends UpstreamClient {

    /**
     * Retrieves the repositories from the upstream server. This stream of repositories is unfiltered with respect to
     * what is mirrored locally. For {@link UpstreamServerType#BITBUCKET_SERVER server} upstreams all repositories are
     * streamed. For {@link UpstreamServerType#BITBUCKET_CLOUD cloud} upstreams only repositories belonging to the
     * {@link UpstreamServer#getAccountId() team account} will be streamed.
     * <p/>
     * The stream is backed by one or more blocking remote requests to the upstream.
     *
     * @return the stream of repositories on the upstream server
     */
    @Nonnull
    Stream<ExternalRepository> getRepositories();

    /**
     * Retrieves a repository from the upstream server.
     *
     * @param repoId the ID of the repository on the upstream server
     * @return a promise of the repository - the promised value being null if it does not exist
     */
    @Nonnull
    Promise<ExternalRepository> getRepository(@Nonnull String repoId);

    /**
     * Checks whether the mirror is installed in the upstream server
     *
     * @return {@code true} if the mirror is installed, otherwise {@code false}
     * @throws UpstreamServerRequestFailedException if the request fails (response status is not 200)
     */
    @Nonnull
    Promise<Boolean> isMirrorInstalled();
}
