/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with this
 * work for additional information regarding copyright ownership. The ASF
 * licenses this file to You under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package org.apache.sling.testing.clients;

import org.apache.http.*;
import org.apache.http.annotation.Immutable;
import org.apache.http.client.*;
import org.apache.http.client.methods.*;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.message.BasicHttpRequest;
import org.apache.http.protocol.HttpContext;
import org.apache.sling.testing.clients.util.HttpUtils;
import org.slf4j.LoggerFactory;

import java.io.Closeable;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * The abstract base client for all implementing integration test clients.
 */
@Immutable
public class AbstractSlingClient implements HttpClient, Closeable {

    private final org.slf4j.Logger log = LoggerFactory.getLogger(getClass());

    private final static URI slash = URI.create("/");

    /**
     * The clientId for the client, generated automatically during instantiation of client.
     */
    private final String clientId;

    /**
     * The HttpClient object to which http calls are delegated.
     * It can be shared across multiple AbstractSlingClients (by using adaptTo())
     */
    private final CloseableHttpClient http;

    /**
     * A wrapper object containing the sling config for this client.
     * It can be shared across multiple AbstractSlingClients (by using adaptTo())
     */
    private final SlingClientConfig config;

    /**
     * Constructor used by Builders and adaptTo(). <b>Should never be called directly from the code.</b>
     *
     * @param http http client to handle the delegated calls
     * @param config immutable object holding the config
     * @throws ClientException if the client could not be initialized
     */
    AbstractSlingClient(CloseableHttpClient http, SlingClientConfig config) throws ClientException {
        // Generate client ID
        this.clientId = this.getClass() + "-" + UUID.randomUUID().toString();
        this.http = http;
        this.config = config;
    }

    /**
     * Returns the unique id for this client, generated automatically during instantiation.<br>
     *
     * @return client's unique id
     */
    protected String getClientId() {
        return clientId;
    }

    /**
     * <p>Base HTTP URI of the server under test. It includes the context path, if present, and always ends with a slash</p>
     * <p>Example: {@code http://localhost:8080/a/}</p>
     *
     * @return the server's URL
     */
    public URI getUrl() {
        return config.getUrl();
    }


    /**
     * Returns the name of the user that will be used to authenticate the requests (by basic auth, if not replaced).
     *
     * @return user's name
     */
    public String getUser() {
        return config.getUser();
    }

    /**
     * Returns the password of the user that will be used to authenticate the requests (by basic auth, if not replaced).
     *
     * @return user's password
     */
    public String getPassword() {
        return config.getPassword();
    }

    /**
     * <p>Gets the full URL for a given path.</p>
     *
     * <p>The input path is considered relative to server url path ("/" or context path), even though it starts with a slash.
     * The path is relativized and appended to the {@code server url}.</p>
     *
     * <p>Note: in the case of a server url with context path - the input path should not contain the context path, otherwise
     * it will be duplicated in the resulting url</p>
     *
     * @param path the relative path
     * @return the absolute URI
     * @throws IllegalArgumentException if path cannot be parsed into an URI
     * @throws NullPointerException if path is null
     */
    public URI getUrl(String path) {
        try {
            URI pathUri = slash.relativize(new URI(path));
            return getUrl().resolve(pathUri);
        } catch (URISyntaxException e) {
            throw new IllegalArgumentException(e);
        }
    }

    /**
     * Creates a full URL for a given path with additional parameters. Same as {@link #getUrl(String)}, but adds the parameters in the URI.
     *
     * @param path path relative to server url; can start with / but should not include the server context path
     * @param parameters url parameters to be added to the url
     * @return full url as URI
     * @throws IllegalArgumentException if path or parameters cannot be parsed into an URI
     * @throws NullPointerException if path is null
     */
    public URI getUrl(String path, List<NameValuePair> parameters) {
        // add server url and path
        URIBuilder uriBuilder = new URIBuilder(getUrl(path));
        // add parameters
        parameters = (parameters != null) ? parameters : new ArrayList<NameValuePair>(0);
        uriBuilder.addParameters(parameters);

        try {
            return uriBuilder.build();
        } catch (URISyntaxException e) {
            throw new IllegalArgumentException(e);
        }
    }

    /**
     * <p>Transforms an external {@code url} into a sling path, by subtracting the {@code server url} (incl. contextPath).
     * The returned path will not contain the context path, so it can be used with {@link #getUrl(String)}</p>
     *
     * <p>The url can be absolute (incl. hostname) or relative to root (starts with "/").</p>
     *
     * <p>If the server url is not a prefix of the given url, it returns the given url</p>
     *
     * <p>If the url is just a path, it returns the path (with leading slash if not already present)</p>
     *
     * @param url full url
     * @return sling path
     */
    public URI getPath(URI url) {
        // special case for urls that are server urls, but without trailing slash
        if (url.relativize(getUrl()).equals(URI.create(""))) {
            return slash;
        }

        URI contextPath = URI.create(getUrl().getPath());
        URI relativeUrl = contextPath.relativize(slash.resolve(url));

        if (relativeUrl.relativize(contextPath).equals(URI.create(""))) {
            return slash;
        }

        return slash.resolve(getUrl().relativize(relativeUrl));
    }

    /**
     * Extracts the relative sling path (to server url) from an url. Identical to {@link AbstractSlingClient#getPath(URI)},
     * except that it also parses the String int URI
     *
     * @param url string containing the full url
     * @return relative path as URI
     * @throws IllegalArgumentException if the parameter cannot be parsed
     * @throws NullPointerException if url is null
     */
    public URI getPath(String url) {
        try {
            return getPath(new URI(url));
        } catch (URISyntaxException e) {
            throw new IllegalArgumentException(e);
        }
    }

    /**
     * <p>Returns an instance of any class extending the AbstractSlingClient. The new client will
     * use the the same {@link HttpClient} and {@link SlingClientConfig} </p>
     *
     * @param clientClass the type of client requested, identified by its Class
     * @param <T>         any class extending the AbstractSlingClient
     * @return instance of a class extending the AbstractSlingClient
     * @throws ClientException if client can't be instantiated
     */
    @SuppressWarnings("unchecked")
    public <T extends AbstractSlingClient> T adaptTo(Class<T> clientClass) throws ClientException {
        T client;
        try {
            Constructor cons = clientClass.getConstructor(CloseableHttpClient.class, SlingClientConfig.class);
            client = (T) cons.newInstance(this.http, this.config);
        } catch (Exception e) {
            throw new ClientException("Could not initialize client: '" + clientClass.getCanonicalName() + "'.", e);
        }
        return client;
    }

    /**
     * Gets the value for {@code key} from the generic values
     *
     * @param key the key
     * @return the value
     */
    public String getValue(String key) {
        return this.config.getValues().get(key);
    }

    /**
     * Adds the extra {@code key, value} to the generic values
     *
     * @param key the key for witch to add a value
     * @param value the value
     */
    public void addValue(String key, String value) {
        this.config.getValues().put(key, value);
    }

    /**
     * Checks whether the handler has the given generic value
     *
     * @param key the key
     * @return true if the value was found
     */
    public boolean hasValue(String key) {
        return config.getValues().containsKey(key);
    }

    /**
     * Returns the extra values map
     *
     * @return the map of values
     */
    public Map<String, String> getValues() {
        return config.getValues();
    }

    /**
     * @return the cookie store reference
     */
    public CookieStore getCookieStore() {
        return config.getCookieStore();
    }

    /**
     * @return the credentials provider
     */
    public CredentialsProvider getCredentialsProvider() {
        return config.getCredsProvider();
    }

    //
    // HTTP convenience methods
    //

    /**
     * <p>Executes an HTTP request, WITHOUT consuming the entity in the response. The caller is responsible for consuming the entity or
     * closing the response's InputStream in order to release the connection.
     * Otherwise, the client might run out of connections and will block</p>
     *
     * <p><b>Use this with caution and only if necessary for streaming</b>, otherwise use the safe method
     * {@link #doRequest(HttpUriRequest, List, int...)}</p>
     *
     * <p>Adds the headers and checks the response against expected status</p>
     *
     * @param request the request to be executed
     * @param headers optional headers to be added to the request
     * @param expectedStatus if passed, the response status is checked against it/them, and has to match at least one of them
     * @return the response, with the entity not consumed
     * @throws ClientException if the request could not be executed
     */
    public SlingHttpResponse doStreamRequest(HttpUriRequest request, List<Header> headers, int... expectedStatus)
            throws ClientException {
        // create context from config
        HttpClientContext context = createHttpClientContextFromConfig();

        // add headers
        if (headers != null) {
            request.setHeaders(headers.toArray(new Header[headers.size()]));
        }

        try {
            log.debug("request {} {}", request.getMethod(), request.getURI());
            SlingHttpResponse response = new SlingHttpResponse(this.execute(request, context));
            log.debug("response {}", HttpUtils.getHttpStatus(response));
            // Check the status and throw a ClientException if it doesn't match expectedStatus, but close the entity before
            if (expectedStatus != null && expectedStatus.length > 0) {
                try {
                    HttpUtils.verifyHttpStatus(response, expectedStatus);
                } catch (ClientException e) {
                    // catch the exception to make sure we close the entity before re-throwing it
                    response.close();
                    throw e;
                }
            }

            return response;
        } catch (IOException e) {
            throw new ClientException("Could not execute http request", e);
        }
    }

    /**
     * <p>Executes a raw HTTP request, WITHOUT consuming the entity in the response. The caller is responsible for consuming the entity or
     * closing the response's InputStream in order to release the connection.
     * Otherwise, the client might run out of connections and will block</p>
     *
     * <p><b>Use this with caution and only if necessary for custom methods or for paths that must not be encoded</b>,
     * otherwise use the safe method {@link #doRequest(HttpUriRequest, List, int...)}</p>
     *
     * <p>It behaves as {@link #doStreamRequest(HttpUriRequest, List, int...)}, so the entity is not consumed.</p>
     * <p>Adds the headers and checks the response against expected status</p>
     *
     * @param method the request to be executed
     * @param uri the uri to be sent as it is (will not prepend the context path)
     * @param headers optional headers to be added to the request
     * @param expectedStatus if passed, the response status is checked against it/them, and has to match at least one of them
     * @return the response, with the entity not consumed
     * @throws ClientException if the request could not be executed
     */
    public SlingHttpResponse doRawRequest(String method, String uri, List<Header> headers, int... expectedStatus)
            throws ClientException {
        // create context from config
        HttpClientContext context = createHttpClientContextFromConfig();

        HttpHost host = new HttpHost(getUrl().getHost(), getUrl().getPort(), getUrl().getScheme());
        HttpRequest request = new BasicHttpRequest(method, uri);

        // add headers
        if (headers != null) {
            request.setHeaders(headers.toArray(new Header[headers.size()]));
        }

        try {
            log.debug("request {} {}", method, uri);
            SlingHttpResponse response = new SlingHttpResponse(this.execute(host, request, context));
            log.debug("response {}", HttpUtils.getHttpStatus(response));
            // Check the status and throw a ClientException if it doesn't match expectedStatus, but close the entity before
            if (expectedStatus != null && expectedStatus.length > 0) {
                try {
                    HttpUtils.verifyHttpStatus(response, expectedStatus);
                } catch (ClientException e) {
                    // catch the exception to make sure we close the entity before re-throwing it
                    response.close();
                    throw e;
                }
            }

            return response;
        } catch (IOException e) {
            throw new ClientException("Could not execute http request", e);
        }
    }

    private HttpClientContext createHttpClientContextFromConfig() {
        // create context from config
        HttpClientContext context = HttpClientContext.create();

        if (config.getCookieStore() != null) {
            context.setCookieStore(config.getCookieStore());
        }

        if (config.getCredsProvider() != null) {
            context.setCredentialsProvider(config.getCredsProvider());
        }

        if (config.getAuthCache() != null) {
            context.setAuthCache(config.getAuthCache());
        }

        return context;
    }

    /**
     * <p>Executes a GET request WITHOUT consuming the entity in the response. The caller is responsible to close the connection.
     * Otherwise, the client might run out of connections and will block</p>
     *
     * <p><b>Use this with caution and only if necessary for streaming</b>, otherwise use the safe method
     * {@link #doGet(String, List, List, int...)}</p>
     *
     * <p>Adds the given parameters and headers and checks the response against expected status</p>
     * @param requestPath path relative to client url
     * @param parameters optional url parameters to be added
     * @param headers optional headers to be added
     * @param expectedStatus if passed, the response status will have to match one of them
     * @return the response with the entity not consumed
     * @throws ClientException if the request could not be executed
     */
    public SlingHttpResponse doStreamGet(String requestPath, List<NameValuePair> parameters, List<Header> headers, int... expectedStatus)
            throws ClientException {
        // create full uri, including server url, given path and given parameters
        URI uri = getUrl(requestPath, parameters);
        // execute request
        HttpUriRequest request = new HttpGet(uri);
        return doStreamRequest(request, headers, expectedStatus);
    }

    /**
     * <p>Executes a POST request WITHOUT consuming the entity in the response. The caller is responsible to close the connection</p>
     *
     * <p><b>Use this with caution and only if necessary for streaming</b>, otherwise use the safe method
     * {@link #doPost(String, HttpEntity, List, int...)}</p>
     *
     * <p>Adds the headers and checks the response against expected status</p>
     * @param requestPath path relative to client url
     * @param entity http entity to be sent by POST
     * @param headers optional headers to be added
     * @param expectedStatus if passed, the response status will have to match one of them
     * @return the response with the entity not consumed
     * @throws ClientException if the request could not be executed
     */
    public SlingHttpResponse doStreamPost(String requestPath, HttpEntity entity, List<Header> headers, int... expectedStatus)
            throws ClientException {
        HttpEntityEnclosingRequestBase request = new HttpPost(getUrl(requestPath));
        if (entity != null) {
            request.setEntity(entity);
        }
        return doStreamRequest(request, headers, expectedStatus);
    }

    /**
     * <p>Execute an HTTP request and consumes the entity in the response. The content is cached and can be retrieved using
     * {@code response.getContent()}.
     * This method is safe to use because it closes the entity so the caller has no responsibility.</p>
     *
     * <p>This means the response entity SHOULD NOT BE USED to read the content, e.g. {@code response.getEntity().getContent()}</p>
     *
     * @param request the request to be executed
     * @param headers optional headers to be added to the request
     * @param expectedStatus if passed, the response status will have to match one of them
     * @return the response with the entity consumed and the content cached
     * @throws ClientException if the request could not be executed
     */
    public  SlingHttpResponse doRequest(HttpUriRequest request, List<Header> headers, int... expectedStatus) throws ClientException {
        SlingHttpResponse response = doStreamRequest(request, headers, expectedStatus);

        // Consume entity and cache the content so the connection is closed
        response.getContent();

        return response;
    }

    /**
     * <p>Executes a GET request and consumes the entity in the response (so the connection is closed immediately)
     * The content is cached and can be retrieved using {@code response.getContent()}.</p>
     *
     * <p>Adds the passed parameters and headers and checks the expected status</p>
     *
     * @param requestPath path relative to client url
     * @param parameters optional url parameters to be added
     * @param headers optional headers to be added
     * @param expectedStatus if passed, the response status will have to match one of them
     * @return the response with the entity consumed amd the content cached
     * @throws ClientException if the request could not be executed
     */
    public SlingHttpResponse doGet(String requestPath, List<NameValuePair> parameters, List<Header> headers, int... expectedStatus)
            throws ClientException {
        SlingHttpResponse response = doStreamGet(requestPath, parameters, headers, expectedStatus);

        // Consume entity and cache the content so the connection is closed
        response.getContent();

        return response;
    }

    /**
     * <p>Executes a GET request and consumes the entity in the response (so the connection is closed immediately)
     * The content is cached and can be retrieved using {@code response.getContent()}.</p>
     *
     * <p>Adds the passed parameters and checks the expected status</p>
     *
     * @param requestPath path relative to client url
     * @param parameters optional url parameters to be added
     * @param expectedStatus if passed, the response status will have to match one of them
     * @return the response with the entity consumed amd the content cached
     * @throws ClientException if the request could not be executed
     */
    public SlingHttpResponse doGet(String requestPath, List<NameValuePair> parameters, int... expectedStatus)
            throws ClientException {
        return doGet(requestPath, parameters, null, expectedStatus);
    }

    /**
     * <p>Executes a GET request and consumes the entity in the response (so the connection is closed immediately)
     * The content is cached and can be retrieved using {@code response.getContent()}.</p>
     *
     * @param requestPath path relative to client url
     * @param expectedStatus if passed, the response status will have to match one of them
     * @return the response with the entity consumed amd the content cached
     * @throws ClientException if the request could not be executed
     */
    public SlingHttpResponse doGet(String requestPath, int... expectedStatus)
            throws ClientException {
        return doGet(requestPath, null, null, expectedStatus);
    }

    /**
     * <p>Executes a HEAD request</p>
     *
     * <p>Adds the passed parameters and headers and checks the expected status</p>
     *
     * @param requestPath path relative to client url
     * @param parameters optional url parameters to be added
     * @param headers optional headers to be added
     * @param expectedStatus if passed, the response status will have to match one of them
     * @return the response
     * @throws ClientException if the request could not be executed
     */
    public SlingHttpResponse doHead(String requestPath, List<NameValuePair> parameters, List<Header> headers, int... expectedStatus)
            throws ClientException {
        HttpUriRequest request = new HttpHead(getUrl(requestPath, parameters));
        return doRequest(request, headers, expectedStatus);
    }


    /**
     * <p>Executes a POST request and consumes the entity in the response. The content is cached and be retrieved by calling
     * {@code response.getContent()}</p>
     *
     * <p>Adds the passed entity and headers and checks the expected status</p>
     *
     * @param requestPath path relative to client url
     * @param entity the entity to be added to request
     * @param headers optional headers to be added
     * @param expectedStatus if passed, the response status will have to match one of them
     * @return the response with the entity consumed and the content cached
     * @throws ClientException if the request could not be executed
     */
    public SlingHttpResponse doPost(String requestPath, HttpEntity entity, List<Header> headers, int... expectedStatus)
            throws ClientException {
        HttpEntityEnclosingRequestBase request = new HttpPost(getUrl(requestPath));
        if (entity != null) {
            request.setEntity(entity);
        }
        return doRequest(request, headers, expectedStatus);
    }

    /**
     * <p>Executes a POST request and consumes the entity in the response. The content is cached and be retrieved by calling
     * {@code response.getContent()}</p>
     *
     * <p>Adds the passed entity and checks the expected status</p>
     *
     * @param requestPath path relative to client url
     * @param entity the entity to be added to request
     * @param expectedStatus if passed, the response status will have to match one of them
     * @return the response with the entity consumed and the content cached
     * @throws ClientException if the request could not be executed
     */
    public SlingHttpResponse doPost(String requestPath, HttpEntity entity, int... expectedStatus)
            throws ClientException {
        return doPost(requestPath, entity, null, expectedStatus);
    }

    /**
     * <p>Executes a PUT request and consumes the entity in the response. The content is cached and be retrieved by calling
     * {@code response.getContent()}</p>
     *
     * <p>Adds the passed entity and headers and checks the expected status</p>
     *
     * @param requestPath path relative to client url
     * @param entity the entity to be added to request
     * @param headers optional url parameters to be added
     * @param expectedStatus if passed, the response status will have to match one of them
     * @return the response with the entity consumed and the content cached
     * @throws ClientException if the request could not be executed
     */
    public SlingHttpResponse doPut(String requestPath, HttpEntity entity, List<Header> headers, int... expectedStatus)
            throws ClientException {
        HttpEntityEnclosingRequestBase request = new HttpPut(getUrl(requestPath));
        if (entity != null) {
            request.setEntity(entity);
        }
        return doRequest(request, headers, expectedStatus);
    }

    /**
     * <p>Executes a PATCH request and consumes the entity in the response. The content is cached and be retrieved by calling
     * {@code response.getContent()}</p>
     *
     * <p>Adds the passed entity and headers and checks the expected status</p>
     *
     * @param requestPath path relative to client url
     * @param entity the entity to be added to request
     * @param headers optional url parameters to be added
     * @param expectedStatus if passed, the response status will have to match one of them
     * @return the response with the entity consumed and the content cached
     * @throws ClientException if the request could not be executed
     */
    public SlingHttpResponse doPatch(String requestPath, HttpEntity entity, List<Header> headers, int... expectedStatus)
            throws ClientException {
        HttpEntityEnclosingRequestBase request = new HttpPatch(getUrl(requestPath));
        if (entity != null) {
            request.setEntity(entity);
        }
        return doRequest(request, headers, expectedStatus);
    }

    /**
     * <p>Executes a DELETE request and consumes the entity in the response. The content is cached and be retrieved by calling
     * {@code response.getContent()}</p>
     *
     * <p>Adds the passed parameters and headers and checks the expected status</p>
     *
     * @param requestPath path relative to client url
     * @param parameters optional url parameters to be added
     * @param headers optional url parameters to be added
     * @param expectedStatus if passed, the response status will have to match one of them
     * @return the response with the entity consumed and the content cached
     * @throws ClientException if the request could not be executed
     */
    public SlingHttpResponse doDelete(String requestPath, List<NameValuePair> parameters, List<Header> headers, int... expectedStatus)
            throws ClientException {
        HttpUriRequest request = new HttpDelete(getUrl(requestPath, parameters));
        return doRequest(request, headers, expectedStatus);
    }

    @Override
    /**
     * <p>Closes the http client and makes sure all the underlying resources, like the connection manager, shut down </p>
     *
     */
    public void close() throws IOException {
        this.http.close();
    }


    //
    // HttpClient  base methods
    //

    @Deprecated
    @SuppressWarnings("deprecation")
    public org.apache.http.params.HttpParams getParams() {
        return this.http.getParams();
    }

    @Deprecated
    @SuppressWarnings("deprecation")
    public org.apache.http.conn.ClientConnectionManager getConnectionManager() {
        return this.http.getConnectionManager();
    }

    @SuppressWarnings("DuplicateThrows")
    public HttpResponse execute(HttpUriRequest request) throws IOException, ClientProtocolException {
        return this.http.execute(request);
    }

    // maybe throw UnsupportedMethodException
    @SuppressWarnings("DuplicateThrows")
    public CloseableHttpResponse execute(HttpUriRequest request, HttpContext context)
            throws IOException, ClientProtocolException {
        return this.http.execute(request, context);
    }

    @SuppressWarnings("DuplicateThrows")
    public HttpResponse execute(HttpHost target, HttpRequest request)
            throws IOException, ClientProtocolException {
        return this.http.execute(target, request);
    }

    @SuppressWarnings("DuplicateThrows")
    public CloseableHttpResponse execute(HttpHost target, HttpRequest request, HttpContext context)
            throws IOException, ClientProtocolException {
        return this.http.execute(target, request, context);
    }

    @SuppressWarnings("DuplicateThrows")
    public <T> T execute(HttpUriRequest request, ResponseHandler<? extends T> responseHandler)
            throws IOException, ClientProtocolException {
        return this.http.execute(request, responseHandler);
    }

    @SuppressWarnings("DuplicateThrows")
    public <T> T execute(HttpUriRequest request, ResponseHandler<? extends T> responseHandler, HttpContext context)
            throws IOException, ClientProtocolException {
        return this.http.execute(request, responseHandler, context);
    }

    @SuppressWarnings("DuplicateThrows")
    public <T> T execute(HttpHost target, HttpRequest request, ResponseHandler<? extends T> responseHandler)
            throws IOException, ClientProtocolException {
        return this.http.execute(target, request, responseHandler);
    }

    @SuppressWarnings("DuplicateThrows")
    public <T> T execute(HttpHost target, HttpRequest request, ResponseHandler<? extends T> responseHandler, HttpContext context)
            throws IOException, ClientProtocolException {
        return this.http.execute(target, request, responseHandler, context);
    }
}
