package com.atlassian.stash.hosting;

import com.atlassian.bitbucket.test.DefaultFuncTestData;
import com.atlassian.bitbucket.test.ProcessResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Optional;

import static java.util.Optional.empty;

/**
 * Tests functionality specific to the {@link HttpScmTransport HTTP transport}.
 */
public class HttpScmTransport implements ScmTransport {

    private static final Logger LOG = LoggerFactory.getLogger(HttpScmTransport.class);

    private String baseUrl;

    private String servletPath = "/scm/";

    public HttpScmTransport(String username, String password) throws Exception {
        this(DefaultFuncTestData.getBaseURL(), username, password);
    }

    public HttpScmTransport(String baseUrl, String username, String password) throws Exception {
        this.baseUrl = interpolateUserInfo(baseUrl, username, password);
    }

    @Override
    public void init() throws IOException {
        LOG.info("Initialising HTTP transport...");
    }

    @Override
    public void clone(File repository, String projectKey, String repositorySlug, String... options) throws IOException {
        clone(repository, empty(), projectKey, repositorySlug, options);
    }

    @Override
    public void clone(File repository, Optional<String> namespace, String projectKey, String repositorySlug, String... options) throws IOException {
        ScmTransportHelper.clone(repository, repositoryUrl(namespace, projectKey, repositorySlug), options);
    }

    public ProcessResult deleteBranch(File repository, String projectKey, String repositorySlug, String branch, String... options) throws IOException {
        return deleteBranch(repository, empty(), projectKey, repositorySlug, branch, options);
    }
    
    public ProcessResult deleteBranch(File repository, Optional<String> namespace, String projectKey, String repositorySlug, String branch, String... options) throws IOException {
        return ScmTransportHelper.deleteBranch(repository, repositoryUrl(namespace, projectKey, repositorySlug), branch, options);
    }

    @Override
    public void fetch(File repository, String projectKey, String repositorySlug, String... options) throws IOException {
        fetch(repository, empty(), projectKey, repositorySlug, options);
    }

    @Override
    public void fetch(File repository, Optional<String> namespace, String projectKey, String repositorySlug, String... options) throws IOException {
        ScmTransportHelper.fetch(repository, repositoryUrl(namespace, projectKey, repositorySlug), options);
    }

    @Override
    public void fetchRefSpec(File repository, String projectKey, String repositorySlug, String refSpec, String... options) throws IOException {
        fetchRefSpec(repository, empty(), projectKey, repositorySlug, refSpec, options);
    }

    @Override
    public void fetchRefSpec(File repository, Optional<String> namespace, String projectKey, String repositorySlug, String refSpec, String... options) throws IOException {
        ScmTransportHelper.fetchRefSpec(repository, repositoryUrl(namespace, projectKey, repositorySlug), refSpec, options);
    }

    @Override
    public void pull(File repository, String projectKey, String repositorySlug, String... options) throws IOException {
        pull(repository, empty(), projectKey, repositorySlug, options);
    }

    @Override
    public void pull(File repository, Optional<String> namespace, String projectKey, String repositorySlug, String... options) throws IOException {
        ScmTransportHelper.pull(repository, repositoryUrl(namespace, projectKey, repositorySlug), options);
    }

    @Override
    public ProcessResult pushAllRefs(File repository, String projectKey, String repositorySlug, String... options) throws IOException {
        return pushAllRefs(repository, empty(), projectKey, repositorySlug, options);
    }

    @Override
    public ProcessResult pushAllRefs(File repository, Optional<String> namespace, String projectKey, String repositorySlug, String... options) throws IOException {
        return ScmTransportHelper.pushAllRefs(repository, repositoryUrl(namespace, projectKey, repositorySlug), options);
    }

    private String repositoryUrl(Optional<String> namespace, String projectKey, String repositorySlug) {
        return baseUrl + servletPath + namespace.map(s -> s + "/").orElse("") + projectKey + "/" + repositorySlug + ".git";
    }

    // overrideable to test the deprecated (but supported) /git/ path
    public void setServletPath(String servletPath) {
        this.servletPath = servletPath;
    }

    public String getServletPath() {
        return servletPath;
    }

    private String interpolateUserInfo(String baseUrl, String username, String password) throws URISyntaxException {
        URI uri = new URI(baseUrl);
        baseUrl = new URI(uri.getScheme(), username + ":" + password, uri.getHost(), uri.getPort(), uri.getPath(), uri.getQuery(), uri.getFragment()).toASCIIString();
        return baseUrl;
    }

    @Override
    public String toString() {
        return "HTTP";
    }
}
