package com.atlassian.bitbucket.scm.git.command.merge;

import javax.annotation.Nullable;

/**
 * Describes the possible fast-forward settings for {@code git merge}.
 */
public enum GitMergeFastForward {

    /**
     * Uses the default fast-forward setting for {@code git merge}, which is generally {@link #ON}. Note that
     * {@code --squash} merges apply {@link #ON} differently; see that constant for details.
     */
    DEFAULT,
    /**
     * <i>Always</i> create a merge commit, even if merge target is an ancestor of the commit being merged, meaning
     * the branch pointer could simply be fast-forwarded to the incoming commit without performing a merge.
     * <p>
     * This is the default merge behaviour for {@link GitMerge#normal() normal} merges unless explicitly configured
     * otherwise.
     */
    OFF("--no-ff"),
    /**
     * Only create a merge commit if the merge target is not an ancestor of the commit being merged, meaning it is
     * not possible to fast-forward the branch pointer.
     * <p>
     * When using this mode with a {@link GitMerge#normal() normal} merge, any commit message or other configuration
     * applied to the merge command will have no effect if the merge can be accomplished by fast-forwarding the branch
     * pointer since no commit is created. This mode has no effect on {@link GitMerge#squash() squash} merges, which
     * always produce a new non-merge commit even if the branch pointer can be fast-forwarded.
     */
    ON("--ff"),
    /**
     * <i>Fail</i> if a merge commit would be created, only allowing the "merge" to be performed if the merge target
     * is an ancestor of the commit being merged.
     * <p>
     * For {@link GitMerge#normal() normal} merges this mode will <i>never</i> create a merge commit. As a result, any
     * commit message or other configuration applied to the merge command will <i>always</i> be ignored.
     * <p>
     * For {@link GitMerge#squash() squash} merges this mode will trigger the merge to fail if the source branch is not
     * fast-forward from the target. However, a new commit will <i>always</i> be created--the branch pointer will never
     * be fast-forwarded. The new commit will reference the same <i>tree</i> as the source commit (so it will contain
     * exactly the same changes), but will have its own author and committer details and commit message.
     */
    ONLY("--ff-only");

    private final String flag;

    GitMergeFastForward() {
        flag = null;
    }

    GitMergeFastForward(String flag) {
        this.flag = flag;
    }

    @Nullable
    public String getFlag() {
        return flag;
    }

    /**
     * Indicates whether this fast-forward setting has a specific {@link #getFlag() flag} for use with
     * {@code git merge}. The {@link #DEFAULT default} mode does not require a flag.
     *
     * @return {@code true} if this setting has a {@link #getFlag() flag}; otherwise, {@code false}
     */
    public boolean isFlagged() {
        return flag != null;
    }
}
