package ru.yandex.autotests.httpclient.lite.core;

import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.util.Asserts;
import ru.yandex.autotests.httpclient.lite.core.config.HttpClientConnectionConfig;
import ru.yandex.autotests.httpclient.lite.core.exceptions.BackEndClientParametersException;
import ru.yandex.autotests.httpclient.lite.core.methods.HttpDeleteWithBody;
import ru.yandex.autotests.httpclient.lite.utils.HttpUtils;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;

import static ru.yandex.autotests.httpclient.lite.utils.HttpUtils.aggregate;
import static ru.yandex.autotests.httpclient.lite.utils.HttpUtils.buildURI;


/**
 * @author Roman Kuhta (kuhtich@yandex-team.ru)
 */
public class BackEndRequestBuilder {
    public BackEndRequestBuilder(HttpClientConnectionConfig config) {
        this.config = config;
    }

    public static final List<NameValuePair> EMPTY_CONTEXT = new ArrayList<>();

    private HttpClientConnectionConfig config;

    public HttpClientConnectionConfig getConfig() {
        return config;
    }

    public <T extends BackEndRequestBuilder> T uri(URI uri) {
        this.config
                .scheme(uri.getScheme())
                .host(uri.getHost())
                .path(uri.getPath())
                .port(uri.getPort());
        return (T) this;
    }

    public <T extends BackEndRequestBuilder> T uri(String url) {
        URI uri;
        try {
            uri = buildURI(new URIBuilder(url));
        } catch (URISyntaxException e) {
            throw new BackEndClientParametersException("Failed url parsing", e);
        }
        return uri(uri);
    }

    public URI getUri() {
        return buildURI(getBuilder());
    }

    public final HttpDelete delete(IFormParameters... params) {
        return delete(aggregate(params));
    }

    @SafeVarargs
    public final HttpDelete delete(List<NameValuePair>... params) {
        return new HttpDelete(buildURI(getBuilder().setParameters(aggregate(params))));
    }

    @SafeVarargs
    public final HttpDeleteWithBody delete(HttpEntity entity, List<NameValuePair>... params) {
        HttpDeleteWithBody del = new HttpDeleteWithBody(buildURI(getBuilder().setParameters(aggregate(params))));
        del.setEntity(entity);
        return del;
    }

    public final HttpDeleteWithBody delete(HttpEntity entity, IFormParameters... params) {
        return delete(entity, aggregate(params));
    }

    public final HttpPut put(IFormParameters... params) {
        return put(aggregate(params));
    }

    @SafeVarargs
    public final HttpPut put(List<NameValuePair>... params) {
        return put(null, params);
    }

    public final HttpPut put(HttpEntity entity, IFormParameters... params) {
        return put(entity, aggregate(params));
    }

    @SafeVarargs
    public final HttpPut put(HttpEntity entity, List<NameValuePair>... params) {
        HttpPut put = new HttpPut(buildURI(getBuilder().setParameters(aggregate(params))));
        put.setEntity(entity);
        return put;
    }

    public final HttpPost post(IFormParameters... params) {
        return post(aggregate(params));
    }

    @SafeVarargs
    public final HttpPost post(List<NameValuePair>... params) {
        HttpPost post = new HttpPost(buildURI(getBuilder()));
        post.setEntity(HttpUtils.buildEntity(aggregate(params)));
        return post;
    }

    public final HttpPost post(HttpEntity entity, IFormParameters... params) {
        return post(entity, aggregate(params));
    }

    @SafeVarargs
    public final HttpPost post(HttpEntity entity, List<NameValuePair>... params) {
        HttpPost post = new HttpPost(buildURI(getBuilder().setParameters(aggregate(params))));
        post.setEntity(entity);
        return post;
    }

    public final HttpGet get(IFormParameters... params) {
        return get(aggregate(params));
    }

    public final HttpGet get() {
        return get(new ArrayList<NameValuePair>());
    }

    @SafeVarargs
     public final HttpGet get(List<NameValuePair>... params) {
        return new HttpGet(buildURI(getBuilder().setParameters(aggregate(params))));
    }

    protected URIBuilder getBuilder() {
        Asserts.notNull(config.getScheme(), "Scheme must be specified");
        Asserts.notNull(config.getHost(), "Host must be specified");
        return new URIBuilder()
                .setScheme(config.getScheme())
                .setHost(config.getHost())
                .setPort(config.getPort() == null ? -1 : config.getPort())
                .setPath(config.getPath());
    }

    private static String requestUri(URI uri) {
        return uri.toString();
    }
}
