package com.atlassian.bitbucket.mesh.git.builder.merge;

import com.atlassian.bitbucket.mesh.git.builder.AbstractGitProcessBuilder;
import com.atlassian.bitbucket.mesh.git.builder.GitProcess;
import com.atlassian.bitbucket.mesh.git.builder.GitProcessBuilder;
import com.google.common.base.MoreObjects;

import javax.annotation.Nonnull;

import static java.util.Objects.requireNonNull;

public abstract class AbstractGitMergeBuilder<B extends GitMergeBuilderSupport<B>>
        extends AbstractGitProcessBuilder<B>
        implements GitMergeBuilderSupport<B> {

    protected GitMergeFastForward ff;

    private boolean allowUnrelatedHistories;
    private String commit;
    private boolean quiet;
    private GitMergeVerify verify;

    public AbstractGitMergeBuilder(GitProcessBuilder builder) {
        super(builder.command("merge"));

        ff = GitMergeFastForward.DEFAULT;
        verify = GitMergeVerify.DEFAULT;
    }

    /**
     * Introduced in Git 2.9, {@code --allow-unrelated-histories} allows {@code git merge} to merge commits
     * which have no common ancestor. <i>This was always allowed by {@code git merge} prior to 2.9.</i> As
     * part of adding the flag, that default behavior was changed in {@code git merge}, which now rejects
     * merges between unrelated commits unless this flag is specified.
     *
     * @param value {@code true} to allow {@code git merge} to merge commits which have no common ancestor;
     *              otherwise, {@code false} to reject such merges ({@code false} is the default)
     * @return {@code this}
     */
    @Nonnull
    @Override
    public B allowUnrelatedHistories(boolean value) {
        allowUnrelatedHistories = value;

        return self();
    }

    @Nonnull
    @Override
    public GitProcess<Void> build() {
        return buildWithLoggingHandler();
    }

    @Nonnull
    @Override
    public B commit(String value) {
        commit = value;

        return self();
    }

    @Nonnull
    @Override
    public B ff(GitMergeFastForward value) {
        ff = MoreObjects.firstNonNull(value, GitMergeFastForward.DEFAULT);

        return self();
    }

    @Nonnull
    @Override
    public B quiet(boolean value) {
        quiet = value;

        return self();
    }

    @Nonnull
    @Override
    public B verify(@Nonnull GitMergeVerify value) {
        verify = requireNonNull(value, "verify");

        return self();
    }

    @Override
    protected void applyArguments() {
        if (allowUnrelatedHistories) {
            builder.argument("--allow-unrelated-histories");
        }
        if (quiet) {
            builder.argument("--quiet");
        }
        verify.getFlag().ifPresent(builder::argument);
        builder.commitish(commit);
    }
}
