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

import com.atlassian.stash.internal.scm.git.version.VersionOutputHandler;
import com.atlassian.bitbucket.util.Version;
import com.atlassian.bitbucket.scm.git.command.GitCommandBuilderFactory;
import com.atlassian.bitbucket.scm.git.GitException;
import com.atlassian.bitbucket.scm.git.GitScmConfig;
import com.atlassian.support.tools.spi.RootLevelSupportInfoAppender;
import com.atlassian.support.tools.spi.SupportInfoBuilder;
import org.slf4j.LoggerFactory;

import static com.atlassian.stash.internal.scm.git.stp.GitStpKeys.*;

/**
 * Appends Git information, like the binary in use and its version, to support requests.
 *
 * @since 2.7
 */
public class GitSupportInfoAppender extends RootLevelSupportInfoAppender {

    private final GitCommandBuilderFactory builderFactory;
    private final GitScmConfig config;

    public GitSupportInfoAppender(GitCommandBuilderFactory builderFactory, GitScmConfig config) {
        this.builderFactory = builderFactory;
        this.config = config;
    }

    @Override
    protected void addSupportInfo(SupportInfoBuilder builder) {
        builder = builder.addCategory(GIT); //Replace the top-level builder; everything should go in our own element
        try {
            builder.addValue(GIT_BINARY, config.getBinary());
            builder.addValue(GIT_VERSION, buildVersion());
        } catch (GitException e) {
            //This will handle both GitNotFoundException and GitUnsupportedVersionException by putting the message
            //from the exception in the zip in place of the binary
            builder.addValue(GIT_BINARY, e.getMessage());
        }
    }

    /**
     * Builds a string indicating the version of Git currently in use. If the current version differs from the version
     * that was detected (and cached) when the system was started, the startup version is also included.
     *
     * @since 3.10
     */
    private String buildVersion() {
        Version currentVersion = null;
        try {
            currentVersion = builderFactory.builder().version(new VersionOutputHandler()).call();
        } catch (Exception e) {
            //Getting the current version is best-effort, so if it fails, just let it go
            LoggerFactory.getLogger(getClass()).warn("Failed to retrieve Git version", e);
        }
        Version startupVersion = config.getVersion();

        //If the we couldn't retrieve the current version, or it is the same as the startup version, just
        //use the startup version. Otherwise show both so that it's obvious the Git version has changed
        return currentVersion == null || currentVersion.equals(startupVersion) ?
                startupVersion.toString() :
                currentVersion + " (" + startupVersion + ")";
    }
}
