package com.atlassian.stash.internal.scm.git;

import com.atlassian.stash.internal.scm.git.command.diff.DiffOutputHandler;
import com.atlassian.bitbucket.repository.Repository;
import com.atlassian.bitbucket.scm.AbstractDiffCommandParameters;
import com.atlassian.bitbucket.scm.git.command.GitCommandBuilderFactory;
import com.atlassian.bitbucket.scm.git.command.GitScmCommandBuilder;
import com.atlassian.bitbucket.scm.git.command.diff.GitDiffBuilder;
import com.atlassian.bitbucket.scm.git.command.diff.GitDiffColor;
import com.atlassian.bitbucket.scm.git.command.diff.GitDiffTreeBuilder;
import com.atlassian.bitbucket.scm.git.command.diff.GitDiffWhitespace;
import com.atlassian.bitbucket.scm.git.command.revlist.GitRevListBuilder;
import org.apache.commons.lang3.ObjectUtils;

import java.util.Set;

public class AbstractGitCompareCommandFactory {

    protected final GitCommandBuilderFactory builderFactory;
    protected final GitRepositoryConfig repositoryConfig;
    protected final InternalGitScmConfig config;

    protected AbstractGitCompareCommandFactory(GitCommandBuilderFactory builderFactory,
                                               GitRepositoryConfig repositoryConfig,
                                               InternalGitScmConfig config) {
        this.builderFactory = builderFactory;
        this.config = config;
        this.repositoryConfig = repositoryConfig;
    }

    protected GitDiffTreeBuilder diffTree(Repository repository, String ancestor, String rev, Set<String> paths) {
        GitDiffTreeBuilder builder = getBuilderFactory(repository).diffTree()
                .ancestor(ancestor)
                .merges(false)
                .paths(paths)
                .recursive(true)
                .rev(rev);
        return repositoryConfig.getDiffStrategy(repository).apply(builder);
    }

    protected GitRevListBuilder revList(Repository fromRepository, String fromRef, Repository toRepository, String toRef) {
        return getBuilderFactory(toRepository, fromRepository).revList()
                .revs(fromRef, "^" + toRef);
    }

    protected GitDiffBuilder diff(Repository repository, String ancestor, String rev, AbstractDiffCommandParameters parameters) {
        GitDiffBuilder builder = getBuilderFactory(repository).diff()
                .ancestor(ancestor)
                .color(GitDiffColor.NEVER)
                .dstPrefix(DiffOutputHandler.DST_PREFIX)
                .whitespace(GitDiffWhitespace.fromDiffWhitespace(parameters.getWhitespace()))
                .paths(parameters.getPaths())
                .rev(rev)
                .srcPrefix(DiffOutputHandler.SRC_PREFIX);
        if (parameters.hasContextLines()) {
            builder.contextLines(parameters.getContextLines());
        }
        return builder;
    }

    protected GitScmCommandBuilder getBuilderFactory(Repository repository) {
        return builderFactory.builder(repository);
    }

    protected GitScmCommandBuilder getBuilderFactory(Repository repository, Repository secondaryRepository) {
        GitScmCommandBuilder builder = getBuilderFactory(repository);
        if (ObjectUtils.notEqual(repository.getId(), secondaryRepository.getId())) {
            builder.withEnvironment(InternalGitConstants.ENV_ALTERNATE_OBJECT_DIRS,
                    config.getObjectsDir(secondaryRepository).getAbsolutePath());
        }
        return builder;
    }

}
