package it.com.atlassian.stash.installer.docker;

import com.atlassian.bitbucket.async.WaitCondition;
import com.atlassian.stash.internal.bootstrap.DevBootstrapOperation;
import com.google.common.collect.ImmutableMap;
import com.google.gson.GsonBuilder;
import com.google.gson.internal.LinkedTreeMap;
import org.hamcrest.Description;
import org.junit.Test;

import java.util.Map;

import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertThat;

public class DockerInstallerTest extends BaseDockerInstallerTest {
    private static final String INIT_SCRIPT = "/etc/init.d/atlbitbucket";
    private static final Map<String, String> BITBUCKET_VAR_FILE = ImmutableMap.<String, String>builder()
            .put("app.install.service$Boolean", "true")
            .put("portChoice", "custom")
            .put("httpPort", "7991")
            .put("serverPort", "8007")
            .put("app.bitbucketHome", BITBUCKET_HOME)
            .put("app.defaultInstallDir", "/tmp/bitbucket-install")
            .build();

    @Test
    public void testGitNotFound() {
        String installerLog = runInstaller(BITBUCKET_INSTALLER_BINARY, BITBUCKET_VAR_FILE);
        assertThat(installerLog, containsString("git.rejected.version=Git not found"));

        waitForStart(new WaitCondition() {
            private static final String GIT_NOT_FOUND = "Git was not found";
            private String lastLog;

            @Override
            public boolean test() throws Exception {
                lastLog = bitbucketLog();
                return lastLog.contains(GIT_NOT_FOUND);
            }

            @Override
            public void describeFailure(Description description) throws Exception {
                description.appendText("Expected startup to fail and log to contain '" + GIT_NOT_FOUND + "'. Log:\n" + lastLog);
            }
        });
    }

    @Test
    public void testServiceInstallation() {
        // git is not included in the base image so it may be possible to test its unavailability
        sh("apt-get install -y git");

        String installerLog = runInstaller(BITBUCKET_INSTALLER_BINARY, BITBUCKET_VAR_FILE);

        assertThat("Expected install dir to exist. Installer log: " + installerLog, sh("ls -d " + BITBUCKET_INSTALL_DIR), startsWith("/"));

        assertThat("Expected atlbitbucket user to be created", sh("id atlbitbucket"), containsString("uid="));

        String exportBitbucketHome = sh("grep 'export BITBUCKET_HOME=' " + BITBUCKET_INSTALL_DIR + "/bin/set-bitbucket-home.sh");
        assertThat("Expected script to contain export for BITBUCKET_HOME", exportBitbucketHome, containsString(BITBUCKET_HOME));

        waitForFirstRun();

        String stopOutput = sh(INIT_SCRIPT + " stop");
        assertThat(stopOutput, containsString("Stopped Atlassian Bitbucket"));
    }

    @Test
    public void testElasticsearchExistsOnGoodPort() {
        // git is not included in the base image so it may be possible to test its unavailability
        sh("apt-get install -y git");

        // To check if search is working, we must set up the config such that the FIRST_RUN setup may be skipped
        // The LICENSE_CLUSTERED comes in a line-separated format, for use in this file, we simply have to remove
        // the line breaks
        sh("mkdir -p " + BITBUCKET_HOME + "/shared");
        sh("echo \"setup.displayName=displayName\\n" +
                "setup.baseUrl=http://localhost:7990\\n" +
                "setup.sysadmin.username=admin\\n" +
                "setup.sysadmin.password=admin\\n" +
                "setup.sysadmin.displayName=admin\\n" +
                "setup.license=" + DevBootstrapOperation.LICENSE_CLUSTERED.replace("\n", "") + "\\n" +
                "setup.sysadmin.emailAddress=admin@example.com\\n" +
                "jdbc.driver=org.hsqldb.jdbcDriver\\n" +
                "jdbc.url=jdbc:hsqldb:" + BITBUCKET_HOME + "/data/db;shutdown=true" +
                "jdbc.user=bitbucket\\n" +
                "jdbc.password=bitbucket\" > " + BITBUCKET_HOME + "/shared/bitbucket.properties");

        runInstaller(BITBUCKET_INSTALLER_BINARY, BITBUCKET_VAR_FILE);

        waitForRun();

        waitForElasticsearchSearchable();

        String searchResult = doBitbucketCodeSearch();

        assertThat("Searching should provide back a JSON object", searchResult, not(isEmptyString()));

        GsonBuilder builder = new GsonBuilder();
        LinkedTreeMap result = builder.create().fromJson(searchResult, LinkedTreeMap.class);
        assertThat("We can parse the JSON object", result.size(), equalTo(3));
    }
}
