package com.atlassian.stash.internal.scm.git;

import com.atlassian.bitbucket.project.Project;
import com.atlassian.stash.internal.scm.git.command.diff.DiffStrategy;
import com.atlassian.bitbucket.repository.Repository;
import com.atlassian.bitbucket.user.ApplicationUser;

import javax.annotation.Nonnull;

/**
 * Provides access to per-repository configuration.
 * <p>
 * Implementations of this interface <i>shall</i> allow configuration to be applied <i>at least</i> at the repository
 * and global level. They are <i>encouraged</i> to allow {@link Project project}-level
 * configuration as well, as different projects may wish to configure all of their repositories the same way, and
 * any one server instance may house any number of disparate projects.
 * <p>
 * Note: Because the configuration is currently stored in {@code bitbucket.properties}, no mutator methods are
 * provided by this interface. However, over time, the intention is that this interface be extended with methods
 * to allow per-repository configuration to be updated as well as read.
 *
 * @since 2.1
 */
public interface GitRepositoryConfig {

    /**
     * @return {@link AuthorNameType#USERNAME} if the git name should be taken from the Stash
     *         {@link ApplicationUser#getName() username), otherwise
     *         {@link AuthorNameType#DISPLAYNAME default} to the
     *         {@link ApplicationUser#getDisplayName() display name}.
     * @since 3.0
     */
    @Nonnull
    AuthorNameType getAuthorNameType(@Nonnull Repository repository);

    /**
     * Retrieves the configured {@link DiffStrategy diff strategy} for the specified {@link Repository repository}.
     *
     * @param repository the repository in which the diff command will be run
     * @return the configured strategy, or a default if no strategy has been configured or the configured strategy
     *         is not valid
     * @see DiffStrategy
     */
    @Nonnull
    DiffStrategy getDiffStrategy(@Nonnull Repository repository);

    /**
     * Retrieves a flag indicating whether automatic merging for pull requests is enabled for the specified
     * {@link Repository repository}.
     * <p>
     * Automatic merging is used to display a more useful diff, potentially revealing conflicts which may exist
     * between the branches being merged, and to efficiently determine whether a pull request can be merged by
     * the system, or must be merged manually by a user. However, such merging has performance implications which
     * may not be acceptable in all instances, so it is possible to disable the feature.
     * <p>
     * Note: When automatic merging is disabled there is no performant way to determine whether a pull request can
     * be merged by the system. Under such configuration, the system will assume all pull requests can be merged
     * and allow the merge to pass or fail at merge time.
     *
     * @param repository the repository which the pull request will be merged <i>to</i>
     * @return {@code true} if automatic merging is enabled for the repository; otherwise, {@code false} to show a
     *         simple diff between the source branch and common ancestor
     */
    boolean isAutoMergeEnabled(@Nonnull Repository repository);

    /**
     * Retrieves a flag indicating whether {@code git add --force} should be used to add conflicted files when
     * handling conflicts during pull request automatic merges. <i>This flag will </i>never<i> be used while
     * performing a real merge.</i>
     *
     * @param repository the repository which the pull request will be merged <i>to</i>
     * @return {@code} if automatic merging should use {@code git add --force} when adding conflicted files;
     *         otherwise, {@code false} to use a "safe" {@code git add}
     * @since 2.5
     */
    boolean isForceAddEnabled(@Nonnull Repository repository);
}
