package com.atlassian.bitbucket.mesh.git.builder.fetch;

import com.atlassian.bitbucket.mesh.git.builder.GitProcessBuilderSupport;
import com.atlassian.bitbucket.mesh.repository.Repository;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.nio.file.Path;

/**
 * A builder which can be used to construct a {@link com.atlassian.bitbucket.mesh.git.builder.GitProcess process}
 * for running {@code git fetch}.
 */
public interface GitFetchBuilder extends GitProcessBuilderSupport<GitFetchBuilder> {

    @Nonnull
    GitFetchBuilder atomic(boolean value);

    /**
     * Clears any {@link #negotiationTips negotiation tips} which have been added, allowing the same builder to be
     * reused when constructing multiple fetches.
     *
     * @return {@code this}
     */
    @Nonnull
    GitFetchBuilder clearNegotiationTips();

    /**
     * Clears any {@link #refspecs(Iterable) refspecs} which have been added, allowing the same builder to be reused
     * when constructing multiple fetches for different refs.
     *
     * @return {@code this}
     */
    @Nonnull
    GitFetchBuilder clearRefspecs();

    @Nonnull
    GitFetchBuilder force(boolean value);

    /**
     * @param values the negotiation tips to use for the fetch
     * @return {@code this}
     */
    @Nonnull
    GitFetchBuilder negotiationTips(@Nullable Iterable<String> values);

    /**
     * @param values the negotiation tips to use for the fetch
     * @return {@code this}
     */
    @Nonnull
    GitFetchBuilder negotiationTips(@Nullable String value, @Nullable String... values);

    @Nonnull
    GitFetchBuilder progress(boolean value);

    /**
     * Specifies whether to supply {@code --prune} to prune local branches and tags where the upstream branch
     * or tag has been deleted.
     *
     * @param value {@code true} if local refs which do not exist upstream should be pruned; otherwise {@code false}
     *              to leave such refs in place
     * @return {@code this}
     */
    @Nonnull
    GitFetchBuilder prune(boolean value);

    @Nonnull
    GitFetchBuilder quiet(boolean value);

    @Nonnull
    GitFetchBuilder refspec(String value);

    @Nonnull
    GitFetchBuilder refspecs(Iterable<String> values);

    @Nonnull
    GitFetchBuilder refspecs(String value, String... values);

    /**
     * @param value the directory of the upstream repository to fetch from
     * @return {@code this}
     */
    @Nonnull
    GitFetchBuilder repository(Path value);

    /**
     * Specifies which upstream repository to fetch from.
     *
     * @param value the repository to fetch from
     * @return {@code this}
     */
    @Nonnull
    GitFetchBuilder repository(Repository value);

    /**
     * Specifies which upstream repository to fetch from.
     *
     * @param url the repository URL to fetch from
     * @return {@code this}
     */
    @Nonnull
    GitFetchBuilder repository(String url);

    /**
     * Specifies {@code --tags} or {@code --no-tags}, to control whether {@code git fetch} fetches tags, and which
     * tags it fetches.
     *
     * @param value the tag mode for the command
     * @return {@code this}
     */
    @Nonnull
    GitFetchBuilder tags(@Nonnull GitFetchTagMode value);
}
