package com.atlassian.bitbucket.scm;

import com.atlassian.bitbucket.i18n.I18nService;

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

import static java.util.Optional.empty;

/**
 * Describes a single merge strategy, which controls how commits from one line of development are applied to another.
 * Some strategies may not "merge" at all; others might always merge, even when a merge isn't strictly necessary.
 * <p>
 * Each strategy is expected to have a <i>localizable</i> {@link #getDescriptionKey description} and
 * {@link #getNameKey name}. These values will be displayed in the UI to allow administrators to select which
 * strategy or strategies they wish to use for their repositories. Localized values may be associated with keys
 * by registering an <a href="https://developer.atlassian.com/display/DOCS/Adding+Resources+to+your+Project">"i18n"
 * resource</a> in {@code atlassian-plugin.xml}. The XML for such a resource looks like: {@code <resource
 * type="i18n" name="..." location="..."/>}.
 *
 * @since 4.9
 */
public interface PluginMergeStrategy {

    /**
     * A <i>short, descriptive</i> summary of what the strategy does, suitable for display in a space-constrained
     * UI. The description should make sense to someone familiar with the SCM, but should also be informative for
     * novices to help them make an informed decision on which strategy, or strategies, to use.
     * <p>
     * SCMs are expected to return a <i>key</i>, which will be used to {@link I18nService#getMessage look up a
     * localized description}, rather than a fixed-language description. Localized text can be associated with the
     * key by registering an <a href="https://developer.atlassian.com/display/DOCS/Adding+Resources+to+your+Project">
     * "i18n" resource</a> in {@code atlassian-plugin.xml}.
     *
     * @return a key to look up a localized description
     */
    @Nonnull
    String getDescriptionKey();

    /**
     * Retrieves a flag, or series of flags, which would be familiar to users of the SCM to help identify what the
     * strategy does by relating it to well-known command line functionality. Strategies are <i>not required</i> to
     * provide a flag if there isn't a logical value. For example, if the strategy is implemented by extending or
     * overriding the SCM's standard functionality, there may not be a well-known flag for it.
     * <p>
     * <b>Implementation Note</b>: <i>Implementations may not return {@code null}.</i> They are <i>required</i> to
     * return {@code Optional.empty()} if there is no value. To facilitate a correct implementation, the interface
     * defaults to returning {@code Optional.empty()}. It may be overridden for strategies with a well-known flag.
     *
     * @return a well-known flag, or series of flags, related to the strategy, or {@code Optional.empty()} if there
     *         isn't one
     */
    @Nonnull
    default Optional<String> getFlag() {
        return empty();
    }

    /**
     * Retrieves an <i>SCM-unique</i> identifier for the merge strategy. The identifier returned does <i>not</i>
     * have to be unique across all SCMs; it only needs to be unique within the specific SCM it's returned by.
     * <p>
     * <b>Warning</b>: <i>SCM implementors should choose their IDS with care because they cannot be changed.</i>
     * Additionally, <i>IDs must be 255 characters or less</i>. These IDs will be persisted by the system, to allow
     * administrators to configure which strategy or strategies should be used for various operations (for example,
     * when merging a pull request). Changing a strategy's ID will result in unexpected changes in behavior, and IDs
     * longer than 255 characters cannot be persisted.
     *
     * @return a unique identifier for the strategy, <i>unchanging and 255 characters or less</i>
     */
    @Nonnull
    String getId();

    /**
     * A <i>short, human-readable</i> name for the strategy, like "Fast-forward", suitable for display in a space-
     * constrained UI.
     * <p>
     * SCMs are expected to return a <i>key</i>, which will be used to {@link I18nService#getMessage look up a
     * localized name}, rather than a fixed-language name. Localized text can be associated with the key by registering
     * an <a href="https://developer.atlassian.com/display/DOCS/Adding+Resources+to+your+Project">"i18n" resource</a>
     * in {@code atlassian-plugin.xml}.
     *
     * @return a key to look up a localized name
     */
    @Nonnull
    String getNameKey();

    /**
     * Retrieves a flag indicating whether this strategy is the SCM's default, the strategy it will use if no
     * explicit strategy is requested. <i>SCMs may only have a single default.</i> For SCMs which support more
     * than one strategy, <i>exactly one</i> may be marked as the default.
     * <p>
     * If the SCM has a well-known client, like {@code git} or {@code hg}, the default strategy for the SCM
     * implementation <i>is not required</i> to be the same as the client might use. SCM implementors are free
     * to choose whatever default they feel produces the best results for the majority of use cases. By exposing
     * multiple strategies, administrators are free to select their own default if the SCM implementation's
     * default is not what they're looking for.
     *
     * @return {@code true} if this is the default strategy; otherwise, {@code false} for all other strategies
     */
    boolean isDefault();
}
