package com.atlassian.stash.internal.merge;

import com.atlassian.bitbucket.scm.PluginMergeStrategy;

import javax.annotation.Nonnull;
import java.util.Set;

/**
 * Describes how merges have been configured, identifying the {@link #getDefaultStrategyId default} strategy
 * and the {@link #getEnabledStrategyIds enabled} strategies, as well as all of the available strategies that
 * are supported by the SCM.
 *
 * @since 4.9
 */
public interface MergeConfig {

    /**
     * Retrieves all of the merge strategies that are supported by the SCM, whether they are
     * {@link #isEnabled enabled} or not.
     *
     * @return the available strategies supported by the SCM, whether {@link #isEnabled enabled} or not
     */
    @Nonnull
    Set<PluginMergeStrategy> getAvailableStrategies();

    /**
     * Retrieves the {@link PluginMergeStrategy#getId ID} for the default strategy, which is guaranteed to be
     * both {@link #isEnabled enabled} <i>and</i> {@link #isAvailable available}.
     *
     * @return the default strategy
     */
    @Nonnull
    String getDefaultStrategyId();

    /**
     * Retrieves the {@link PluginMergeStrategy#getId IDs} of the enabled strategies. The
     * {@link #getDefaultStrategyId default} strategy is guaranteed to be enabled, and all
     * of the enabled strategies are guaranteed to be {@link #isAvailable available}.
     *
     * @return the enabled strategies, which are all {@link #isAvailable available} as well
     */
    @Nonnull
    Set<String> getEnabledStrategyIds();

    /**
     * Retrieves the configuration type, identifying the level the configuration was applied at. Since configuration
     * is inherited, the type may be <i>less specific</i> than what was requested.
     *
     * @return the configuration type returned, which may be <i>less specific</i> than the configuration requested
     */
    @Nonnull
    MergeConfigType getType();

    /**
     * Checks whether the specified strategy is {@link #getAvailableStrategies available}, meaning it's
     * supported by the SCM.
     *
     * @param strategyId the strategy to check
     * @return {@code true} if the strategy is {@link #getAvailableStrategies available}; otherwise,
     *         {@code false} if the strategy is not supported by the SCM
     */
    boolean isAvailable(@Nonnull String strategyId);

    /**
     * Checks whether the specified strategy is {@link #getEnabledStrategyIds enabled}, meaning it is both
     * enabled <i>and {@link #isAvailable available}</i>.
     *
     * @param strategyId the strategy to check
     * @return {@code true} if the strategy is {@link #getEnabledStrategyIds enabled} and {@link #isAvailable
     *         available}; otherwise, {@code false} if the strategy is not enabled or not available
     */
    boolean isEnabled(@Nonnull String strategyId);
}
