package com.atlassian.bitbucket.installer.analytics;

import com.google.common.annotations.VisibleForTesting;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Map;

public class PingbackClient {
    private static final String DEFAULT_PINGBACK_SERVER = "https://www.atlassian.com/pingback";
    private static final Logger log = LoggerFactory.getLogger(PingbackClient.class);

    @VisibleForTesting
    private final CloseableHttpClient client;
    private final String pingbackServer;

    public PingbackClient(CloseableHttpClient client) {
        this(client, System.getProperty("installer.pingback.host", DEFAULT_PINGBACK_SERVER));
    }

    public PingbackClient(CloseableHttpClient client, String pingbackServer) {
        this.client = client;
        this.pingbackServer = pingbackServer;
    }

    /**
     * Triggers a pingback to the defined pingback server, and returns the status code.  Note that this method
     * doesn't catch its exceptions so that they can be logged appropriately by the caller.
     *
     * @param product the product generating this pingback
     * @param version the version of the product generating this pingback (eg. "3.6.0")
     * @param serverId a unique id for this pingback session
     * @param pageId the page that is being pinged back from
     * @param additionalParams a map of additional attributes that will be sent with the pingback
     * @return the HTTP status code returned from the pingback call if it was successful
     *
     * @throws URISyntaxException
     * @throws IOException
     */
    public int pingback(String product, String version, String serverId, String pageId, Map<String, String> additionalParams)
        throws URISyntaxException, IOException {
        URIBuilder uriBuilder = new URIBuilder(pingbackServer);
        uriBuilder.addParameter("product", product);
        uriBuilder.addParameter("sid", serverId);
        uriBuilder.addParameter("pg", pageId);
        uriBuilder.addParameter("v", "v" + version);    // v added to be consistent with setup pingbacks

        if (additionalParams != null && !additionalParams.isEmpty()) {
            for (Map.Entry<String, String> entry : additionalParams.entrySet()) {
                uriBuilder.addParameter(entry.getKey(), entry.getValue());
            }
        }

        URI uri = uriBuilder.build();
        HttpGet get = new HttpGet(uri);
        log.debug("Executing pingback with URL {}", uri);
        try (CloseableHttpResponse response = client.execute(get)) {
            int statusCode = response.getStatusLine().getStatusCode();
            log.debug("Pingback to URL {} complete with return code {}", uri, statusCode);
            EntityUtils.consumeQuietly(response.getEntity());
            return statusCode;
        }
    }
}
