package com.atlassian.stash.internal.repository.sync;

import com.atlassian.bitbucket.concurrent.BucketedExecutor;
import com.atlassian.bitbucket.scm.git.GitScmConfig;
import com.atlassian.bitbucket.repository.Repository;

import javax.annotation.Nonnull;

/**
 * Describes a reusable component for retrieving configuration settings for ref synchronization.
 *
 * @since 2.6
 */
public interface RefSyncConfig {

    /**
     * Retrieves the configured limit for the number of characters that can be added to a single command.
     *
     * @return the maximum number of characters that can be added to a command before it must be split
     * @since 3.1
     */
    int getCommandSize();

    /**
     * Retrieves the configured fetch timeout, in seconds, which is applied as both the execution and idle timeout
     * for commands used to synchronize refs.
     *
     * @return the configured fetch timeout
     * @since 4.6
     */
    long getFetchTimeout();

    /**
     * Retrieves the configured merge timeout, in seconds, which is applied as both the execution and idle timeout
     * when merging in changes from upstream to manually synchronize a fork's branch.
     *
     * @return the configured merge timeout
     * @since 4.6
     */
    long getMergeTimeout();

    /**
     * Retrieves a <i>relative path</i> from the root of one repository to another.
     * <p>
     * This is a passthrough to {@link GitScmConfig#getRelativePath(Repository, Repository)
     * GitScmConfig}. It exists here to simplify the various synchronize ref command implementations, which otherwise
     * would need access to both {@link GitScmConfig GitScmConfig} and this. Long term this
     * method should be removed.
     *
     * @param repository the <i>destination</i> repository
     * @param relativeTo the <i>starting</i> repository
     * @return a relative path that, if appended to the {@code relativeTo} repository's path, would point to the
     *         specified {@code repository}
     * @since 3.1
     */
    @Nonnull
    String getRelativePath(@Nonnull Repository repository, @Nonnull Repository relativeTo);

    /**
     * Retrieves the configured delay, in seconds, that the system should wait before synchronizing refs after
     * changes are detected upstream. Longer delays increase the likelihood that changes will be batched, resulting
     * in lower system load, but shorter delays mean new upstream commits are more readily available in forks.
     *
     * @return the configured sync delay
     * @since 3.11
     */
    long getSyncDelay();

    /**
     * Retrieves the configured number of threads to use to process automatic synchronization requests.
     *
     * @return the number of {@link BucketedExecutor BucketedExecutor} threads to use
     *         to process {@link com.atlassian.stash.internal.repository.sync.auto.AutoRefSyncRequest automatic sync
     *         requests}
     * @since 3.3
     */
    int getThreadCount();

    /**
     * Retrieves a flag indicating whether ref synchronization is possible.
     * <p>
     * Depending on the system configuration, ref synchronization may not be able to function correctly. This
     * setting considers the overall configuration and determines whether synchronization is possible.
     *
     * @return {@code true} if the system is configured in a way that supports synchronization; otherwise,
     *         {@code false} if its configuration will interfere with synchronization
     */
    boolean isPossible();
}
