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

import com.atlassian.bitbucket.mesh.git.builder.AbstractGitProcessBuilder;
import com.atlassian.bitbucket.mesh.git.builder.GitProcessBuilder;
import com.google.common.collect.Iterables;

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

public abstract class AbstractGitMergeBaseBuilder<B extends GitMergeBaseBuilderSupport<B>>
        extends AbstractGitProcessBuilder<B>
        implements GitMergeBaseBuilderSupport<B> {

    protected final Set<String> commits;

    protected AbstractGitMergeBaseBuilder(GitProcessBuilder builder) {
        super(builder);

        commits = new LinkedHashSet<>();
    }

    @Nonnull
    @Override
    public B commit(String value) {
        addIfNotBlank(commits, value);

        return self();
    }

    @Nonnull
    @Override
    public B commits(Iterable<String> value) {
        addIfNotBlank(commits, value);

        return self();
    }

    @Nonnull
    @Override
    public B commits(String value, String... values) {
        addIfNotBlank(commits, value, values);

        return self();
    }

    @Override
    protected void applyArguments() {
        applyModeArguments();

        for (String commit : commits) {
            builder.commitish(commit);
        }
        if (commits.size() == 1) {
            //If the caller only passed a single _distinct_ commit ID we have 3 options:
            //- Throw an exception here indicating we need at least 2 commits
            //- Pass a single commit ID to merge-base and let it fail and print a usage block
            //- Pass the same commit ID twice so merge-base will succeed and return that ID
            //
            //This chooses option 3. Why? Because we can't know, at this point in the code, whether the user
            //only provided 1 commit ID, or whether they (likely accidentally) provided the same commit ID
            //twice. Since "git merge-base abc1234 abc1234" doesn't fail, doing the same thing via the builder
            //API probably shouldn't fail either.
            String commitId = Iterables.getOnlyElement(commits);
            builder.argument(commitId); //argument instead of commitish so we only validate once
        }
    }

    protected abstract void applyModeArguments();
}
