/*
 * 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 static org.apache.http.HttpStatus.SC_CREATED;
import static org.apache.http.HttpStatus.SC_OK;

import java.io.File;
import java.net.URI;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.HttpResponseInterceptor;
import org.apache.http.NameValuePair;
import org.apache.http.annotation.Immutable;
import org.apache.http.client.CookieStore;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.RedirectStrategy;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.apache.sling.testing.clients.interceptors.DelayRequestInterceptor;
import org.apache.sling.testing.clients.interceptors.HttpRequestResponseInterceptor;
import org.apache.sling.testing.clients.interceptors.TestDescriptionInterceptor;
import org.apache.sling.testing.clients.util.FormEntityBuilder;
import org.apache.sling.testing.clients.util.HttpUtils;
import org.apache.sling.testing.clients.util.JsonUtils;
import org.apache.sling.testing.clients.util.ServerErrorRetryStrategy;
import org.apache.sling.testing.clients.util.poller.AbstractPoller;
import org.apache.sling.testing.clients.util.poller.Polling;
import org.apache.sling.testing.timeouts.TimeoutsProvider;
import org.codehaus.jackson.JsonNode;

/**
 * <p>The Base class for all Integration Test Clients. It provides generic methods to send HTTP requests to a server. </p>
 *
 * <p>It has methods to perform simple node operations on the server like creating and deleting nodes, etc.
 * on the server using requests. </p>
 */
@Immutable
public class SlingClient extends AbstractSlingClient {

    public static final String DEFAULT_NODE_TYPE = "sling:OrderedFolder";
    public static final String CLIENT_CONNECTION_TIMEOUT_PROP = "sling.client.connection.timeout.seconds";
    public static final String SUDO_COOKIE_NAME = "sling.sudo.cookie.name";

    /**
     * Constructor used by Builders and adaptTo(). <b>Should never be called directly from the code.</b>
     *
     * @param http the underlying HttpClient to be used
     * @param config sling specific configs
     * @throws ClientException if the client could not be created
     *
     * @see AbstractSlingClient#AbstractSlingClient(CloseableHttpClient, SlingClientConfig)
     */
    public SlingClient(CloseableHttpClient http, SlingClientConfig config) throws ClientException {
        super(http, config);
    }

    /**
     * <p>Handy constructor easy to use in simple tests. Creates a client that uses basic authentication.</p>
     *
     * <p>For constructing clients with complex configurations, use a {@link InternalBuilder}</p>
     *
     * <p>For constructing clients with the same configuration, but a different class, use {@link #adaptTo(Class)}</p>
     *
     * @param url url of the server (including context path)
     * @param user username for basic authentication
     * @param password password for basic authentication
     * @throws ClientException never, kept for uniformity with the other constructors
     */
    public SlingClient(URI url, String user, String password) throws ClientException {
        super(Builder.create(url, user, password).buildHttpClient(), Builder.create(url, user, password).buildSlingClientConfig());
    }

    /**
     * Moves a sling path to a new location (:operation move)
     *
     * @param srcPath source path
     * @param destPath destination path
     * @param expectedStatus list of accepted status codes in response
     * @return the response
     * @throws ClientException if an error occurs during operation
     */
    public SlingHttpResponse move(String srcPath, String destPath, int... expectedStatus) throws ClientException {
        UrlEncodedFormEntity entity = FormEntityBuilder.create()
                .addParameter(":operation", "move")
                .addParameter(":dest", destPath)
                .build();

        return this.doPost(srcPath, entity, expectedStatus);
    }

    /**
     * Deletes a sling path (:operation delete)
     *
     * @param path path to be deleted
     * @param expectedStatus list of accepted status codes in response
     * @return the response
     * @throws ClientException if an error occurs during operation
     */
    public SlingHttpResponse deletePath(String path, int... expectedStatus) throws ClientException {
        HttpEntity entity = FormEntityBuilder.create().addParameter(":operation", "delete").build();

        return this.doPost(path, entity, expectedStatus);
    }

    /**
     * Recursively creates all the none existing nodes in the given path using the {@link SlingClient#createNode(String, String)} method.
     * All the created nodes will have the given node type.
     *
     * @param path the path to use for creating all the none existing nodes
     * @param nodeType the node type to use for the created nodes
     * @return the response to the creation of the leaf node
     * @throws ClientException if one of the nodes can't be created
     */
    public SlingHttpResponse createNodeRecursive(final String path, final String nodeType) throws ClientException {
        final String parentPath = getParentPath(path);
        if (!parentPath.isEmpty() && !exists(parentPath)) {
            createNodeRecursive(parentPath, nodeType);
        }

        return createNode(path, nodeType);
    }

    /**
     * Creates the node specified by a given path with the given node type.<br>
     * If the given node type is {@code null}, the node will be created with the default type: {@value DEFAULT_NODE_TYPE}.<br>
     * If the node already exists, the method will return null, with no errors.<br>
     * The method ignores trailing slashes so a path like this <i>/a/b/c///</i> is accepted and will create the <i>c</i> node if the rest of
     * the path exists.
     * 
     * @param path the path to the node to create
     * @param nodeType the type of the node to create
     * @return the sling HTTP response or null if the path already existed
     * @throws ClientException if the node can't be created
     */
    public SlingHttpResponse createNode(final String path, final String nodeType) throws ClientException {
        if (!exists(path)) {

            String nodeTypeValue = nodeType;
            if (nodeTypeValue == null) {
                nodeTypeValue = DEFAULT_NODE_TYPE;
            }

            // Use the property for creating the actual node for working around the Sling issue with dot containing node names.
            // The request will be similar with doing:
            // curl -F "nodeName/jcr:primaryType=nodeTypeValue" -u admin:admin http://localhost:8080/nodeParentPath
            final String nodeName = getNodeNameFromPath(path);
            final String nodeParentPath = getParentPath(path);
            final HttpEntity entity = FormEntityBuilder.create().addParameter(nodeName + "/jcr:primaryType", nodeTypeValue).build();
            return this.doPost(nodeParentPath, entity, SC_OK, SC_CREATED);
        } else {
            return null;
        }
    }

    /**
     * <p>Checks whether a path exists or not by making a GET request to that path with the {@code json} extension</p>
     * @param path path to be checked
     * @return true if GET response returns 200
     * @throws ClientException if the request could not be performed
     */
    public boolean exists(String path) throws ClientException {
        SlingHttpResponse response = this.doGet(path + ".json");
        final int status = response.getStatusLine().getStatusCode();
        return status == SC_OK;
    }

    /**
     * Extracts the parent path from the given String
     *
     * @param path string containing the path
     * @return the parent path if exists or empty string otherwise
     */
    protected String getParentPath(final String path) {
        // TODO define more precisely what is the parent of a folder and of a file
        final String normalizedPath = StringUtils.removeEnd(path, "/");  // remove trailing slash in case of folders
        return StringUtils.substringBeforeLast(normalizedPath, "/");
    }

    /**
     * Extracts the node from path
     *
     * @param path string containing the path
     * @return the node without parent path
     */
    protected String getNodeNameFromPath(final String path) {
        // TODO define the output for all the cases (e.g. paths with trailing slash)
        final String normalizedPath = StringUtils.removeEnd(path, "/");  // remove trailing slash in case of folders
        final int pos = normalizedPath.lastIndexOf('/');
        if (pos != -1) {
            return normalizedPath.substring(pos + 1, normalizedPath.length());
        }
        return normalizedPath;
    }

    /**
     * <p>Checks whether a path exists or not by making a GET request to that path with the {@code json extension} </p>
     * <p>It polls the server and waits until the path exists </p>
     *
     * @deprecated use {@link #waitExists(String, long, long)} instead.
     *
     * @param path path to be checked
     * @param waitMillis time to wait between retries
     * @param retryCount number of retries before throwing an exception
     * @throws ClientException if the path was not found
     * @throws InterruptedException to mark this operation as "waiting"
     */
    @Deprecated
    public void waitUntilExists(final String path, final long waitMillis, int retryCount)
            throws ClientException, InterruptedException {
        AbstractPoller poller =  new AbstractPoller(waitMillis, retryCount) {
            boolean found = false;
            public boolean call() {
                try {
                    found = exists(path);
                } catch (ClientException e) {
                    // maybe log
                    found = false;
                }
                return true;
            }

            public boolean condition() {
                return found;
            }
        };

        boolean found = poller.callUntilCondition();
        if (!found) {
            throw new ClientException("path " + path + " does not exist after " + retryCount + " retries");
        }
    }

    /**
     * <p>Waits until a path exists by making successive GET requests to that path with the {@code json extension} </p>
     * <p>Polls the server until the path exists or until timeout is reached </p>
     * @param path path to be checked
     * @param timeout max total time to wait, in milliseconds
     * @param delay time to wait between checks, in milliseconds
     * @throws TimeoutException if the path was not found before timeout
     * @throws InterruptedException to mark this operation as "waiting", should be rethrown by callers
     * @since 1.1.0
     */
    public void waitExists(final String path, final long timeout, final long delay)
            throws TimeoutException, InterruptedException {

        Polling p = new Polling() {
            @Override
            public Boolean call() throws Exception {
                return exists(path);
            }

            @Override
            protected String message() {
                return "Path " + path + " does not exist after %1$d ms";
            }
        };

        p.poll(timeout, delay);
    }

    /**
     * Sets String component property on a node.
     *
     * @param nodePath       path to the node to be edited
     * @param propName       name of the property to be edited
     * @param propValue      value of the property to be edited
     * @param expectedStatus list of expected HTTP Status to be returned, if not set, 200 is assumed.
     * @return the response object
     * @throws ClientException if something fails during the request/response cycle
     */
    public SlingHttpResponse setPropertyString(String nodePath, String propName, String propValue, int... expectedStatus)
            throws ClientException {
        // prepare the form
        HttpEntity formEntry = FormEntityBuilder.create().addParameter(propName, propValue).build();
        // send the request
        return this.doPost(nodePath, formEntry, HttpUtils.getExpectedStatus(SC_OK, expectedStatus));
    }

    /**
     * Sets a String[] component property on a node.
     *
     * @param nodePath         path to the node to be edited
     * @param propName         name of the property to be edited
     * @param propValueList    List of String values
     * @param expectedStatus   list of expected HTTP Status to be returned, if not set, 200 is assumed.
     * @return                 the response
     * @throws ClientException if something fails during the request/response cycle
     */
    public SlingHttpResponse setPropertyStringArray(String nodePath, String propName, List<String> propValueList, int... expectedStatus)
            throws ClientException {
        // prepare the form
        FormEntityBuilder formEntry = FormEntityBuilder.create();
        for (String propValue : (propValueList != null) ? propValueList : new ArrayList<String>(0)) {
            formEntry.addParameter(propName, propValue);
        }
        // send the request and return the sling response
        return this.doPost(nodePath, formEntry.build(), HttpUtils.getExpectedStatus(SC_OK, expectedStatus));
    }

    /**
     * Sets multiple String properties on a node in a single request
     * @param nodePath path to the node to be edited
     * @param properties list of NameValue pairs with the name and value for each property. String[] properties can be defined
     *                   by adding multiple time the same property name with different values
     * @param expectedStatus list of expected HTTP Status to be returned, if not set, 200 is assumed.
     * @return the response
     * @throws ClientException if the operation could not be completed
     */
    public SlingHttpResponse setPropertiesString(String nodePath, List<NameValuePair> properties, int... expectedStatus)
            throws ClientException {
        // prepare the form
        HttpEntity formEntry = FormEntityBuilder.create().addAllParameters(properties).build();
        // send the request and return the sling response
        return this.doPost(nodePath, formEntry, HttpUtils.getExpectedStatus(SC_OK, expectedStatus));
    }

    /**
     * Returns the JSON content of a node already mapped to a {@link org.codehaus.jackson.JsonNode}.<br>
     * Waits max 10 seconds for the node to be created.
     *
     * @deprecated use {@link #waitExists(String, long, long)} and {@link #doGetJson(String, int, int...)} instead
     * @param path  the path to the content node
     * @param depth the number of levels to go down the tree, -1 for infinity
     * @return a {@link org.codehaus.jackson.JsonNode} mapping to the requested content node.
     * @throws ClientException if something fails during request/response processing
     * @throws InterruptedException to mark this operation as "waiting"
     */
    @Deprecated
    public JsonNode getJsonNode(String path, int depth) throws ClientException, InterruptedException {
        return getJsonNode(path, depth, 500, 20);
    }

    /**
     * Returns JSON format of a content node already mapped to a {@link org.codehaus.jackson.JsonNode}.
     *
     * @deprecated use {@link #waitExists(String, long, long)} and {@link #doGetJson(String, int, int...)} instead
     * @param path                 the path to the content node
     * @param depth                the number of levels to go down the tree, -1 for infinity
     * @param waitMillis           how long it should wait between requests
     * @param retryNumber          number of retries before throwing an exception
     * @param expectedStatus       list of allowed HTTP Status to be returned. If not set,
     *                             http status 200 (OK) is assumed.
     * @return a {@link org.codehaus.jackson.JsonNode} mapping to the requested content node.
     * @throws ClientException if something fails during request/response cycle
     * @throws InterruptedException to mark this operation as "waiting"
     */
    @Deprecated
    public JsonNode getJsonNode(String path, int depth, final long waitMillis, final int retryNumber, int... expectedStatus)
            throws ClientException, InterruptedException {

        // check if path exist and wait if needed
        waitUntilExists(path, waitMillis, retryNumber);

        // check for infinity
        if (depth == -1) {
            path += ".infinity.json";
        } else {
            path += "." + depth + ".json";
        }

        // request the JSON for the page node
        SlingHttpResponse response = this.doGet(path);
        HttpUtils.verifyHttpStatus(response, HttpUtils.getExpectedStatus(SC_OK, expectedStatus));

        return JsonUtils.getJsonNodeFromString(response.getContent());
    }

    /**
     * Returns the {@link org.codehaus.jackson.JsonNode} object corresponding to a content node.
     *
     * @param path the path to the content node
     * @param depth the number of levels to go down the tree, -1 for infinity
     * @param expectedStatus list of allowed HTTP Status to be returned. If not set, 200 (OK) is assumed.
     *
     * @return a {@link org.codehaus.jackson.JsonNode} mapping to the requested content node.
     * @throws ClientException if the path does not exist or something fails during request/response cycle
     * @since 1.1.0
     */
    public JsonNode doGetJson(String path, int depth, int... expectedStatus) throws ClientException {

        // check for infinity
        if (depth == -1) {
            path += ".infinity.json";
        } else {
            path += "." + depth + ".json";
        }

        // request the JSON for the node
        SlingHttpResponse response = this.doGet(path, HttpUtils.getExpectedStatus(SC_OK, expectedStatus));
        return JsonUtils.getJsonNodeFromString(response.getContent());
    }

    /**
     * Uploads a file to the repository. It creates a leaf node typed {@code nt:file}. The intermediary nodes are created with
     * type "sling:OrderedFolder" if parameter {@code createFolders} is true
     *
     * @param file           the file to be uploaded
     * @param mimeType       the MIME Type of the file
     * @param toPath         the complete path of the file in the repository including file name
     * @param createFolders  if true, all non existing parent nodes will be created using node type {@code sling:OrderedFolder}
     * @param expectedStatus list of expected HTTP Status to be returned, if not set, 201 is assumed.
     * @return               the response
     * @throws ClientException if something fails during the request/response cycle
     */
    public SlingHttpResponse upload(File file, String mimeType, String toPath, boolean createFolders, int... expectedStatus)
            throws ClientException {
        // Determine filename and parent folder, depending on whether toPath is a folder or a file
        String toFileName;
        String toFolder;
        if (toPath.endsWith("/")) {
            toFileName = file.getName();
            toFolder = toPath;
        } else {
            toFileName = getNodeNameFromPath(toPath);
            toFolder = getParentPath(toPath);
        }

        if (createFolders) {
            createNodeRecursive(toFolder, "sling:OrderedFolder");
        }

        if (mimeType == null) {
            mimeType = "application/octet-stream";
        }

        HttpEntity entity = MultipartEntityBuilder.create()
                .addBinaryBody(toFileName, file, ContentType.create(mimeType), toFileName)
                .build();

        // return the sling response
        return this.doPost(toFolder, entity, HttpUtils.getExpectedStatus(SC_CREATED, expectedStatus));
    }

    /**
     * Creates a new Folder of type sling:OrderedFolder. Same as using {@code New Folder...} in the Site Admin.
     *
     * @param folderName     The name of the folder to be used in the URL.
     * @param folderTitle    Title of the Folder to be set in jcr:title
     * @param parentPath     The parent path where the folder gets added.
     * @param expectedStatus list of expected HTTP Status to be returned, if not set, 201 is assumed.
     * @return the response
     * @throws ClientException if something fails during the request/response cycle
     */
    public SlingHttpResponse createFolder(String folderName, String folderTitle, String parentPath, int... expectedStatus)
            throws ClientException {
        // we assume the parentPath is a folder, even though it doesn't end with a slash
        parentPath = StringUtils.appendIfMissing(parentPath, "/");
        String folderPath = parentPath + folderName;
        HttpEntity feb = FormEntityBuilder.create()
                .addParameter("./jcr:primaryType", "sling:OrderedFolder")  // set primary type for folder node
                .addParameter("./jcr:content/jcr:primaryType", "nt:unstructured")  // add jcr:content as sub node
                .addParameter("./jcr:content/jcr:title", folderTitle)  //set the title
                .build();

        // execute request and return the sling response
        return this.doPost(folderPath, feb, HttpUtils.getExpectedStatus(SC_CREATED, expectedStatus));
    }

    /**
     * <p>Create a tree structure under {@code parentPath} by providing a {@code content} in one
     * of the supported formats: xml, jcr.xml, json, jar, zip.</p>
     *
     * <p>This is the implementation of {@code :operation import}, as documented in
     * <a href="http://sling.apache.org/documentation/bundles/manipulating-content-the-slingpostservlet-servlets-post.html#importing-content-structures">importing-content-structures</a></p>
     *
     * @param parentPath path where the tree is created
     * @param contentType format of the content
     * @param content string expressing the structure to be created, in the specified format
     * @param expectedStatus list of expected HTTP Status to be returned, if not set, 201 is assumed
     * @return the response
     * @throws ClientException if something fails during the request/response cycle
     */
    public SlingHttpResponse importContent(String parentPath, String contentType, String content, int... expectedStatus)
            throws ClientException {
        HttpEntity entity = FormEntityBuilder.create()
                .addParameter(":operation", "import")
                .addParameter(":contentType", contentType)
                .addParameter(":content", content)
                .build();
        // execute request and return the sling response
        return this.doPost(parentPath, entity, HttpUtils.getExpectedStatus(SC_CREATED, expectedStatus));
    }

    /**
     * <p>Create a tree structure under {@code parentPath} by providing a {@code contentFile} in one
     * of the supported formats: xml, jcr.xml, json, jar, zip.</p>
     *
     * <p>This is the implementation of {@code :operation import}, as documented in
     * <a href="http://sling.apache.org/documentation/bundles/manipulating-content-the-slingpostservlet-servlets-post.html#importing-content-structures">importing-content-structures</a></p>
     *
     * @param parentPath path where the tree is created
     * @param contentType format of the content
     * @param contentFile file containing the structure to be created, in the specified format
     * @param expectedStatus list of expected HTTP Status to be returned, if not set, 200 is assumed
     * @return the response
     * @throws ClientException if something fails during the request/response cycle
     */
    public SlingHttpResponse importContent(String parentPath, String contentType, File contentFile, int... expectedStatus)
            throws ClientException {
        HttpEntity entity = MultipartEntityBuilder.create()
                .addTextBody(":operation", "import")
                .addTextBody(":contentType", contentType)
                .addBinaryBody(":contentFile", contentFile)
                .build();
        // execute request and return the sling response
        return this.doPost(parentPath, entity, HttpUtils.getExpectedStatus(SC_CREATED, expectedStatus));
    }

    /**
     * Wrapper method over {@link #importContent(String, String, String, int...)} for directly importing a json node
     * @param parentPath path where the tree is created
     * @param json json node with the desired structure
     * @param expectedStatus list of expected HTTP Status to be returned, if not set, 201 is assumed
     * @return the response
     * @throws ClientException if something fails during the request/response cycle
     */
    public SlingHttpResponse importJson(String parentPath, JsonNode json, int... expectedStatus)
            throws ClientException {
        return importContent(parentPath, "json", json.toString(), expectedStatus);
    }

    private String getSudoCookieName() {
        return Optional.ofNullable(this.getValue(SUDO_COOKIE_NAME)).orElse("sling.sudo");
    }

    /**
     * Get the UUID of a repository path
     *
     * @param path path in repository
     * @return uuid as String or null if path does not exist
     * @throws ClientException if something fails during request/response cycle
     */
    public String getUUID(String path) throws ClientException {
        if (!exists(path)) {
            return null;
        }
        JsonNode jsonNode = doGetJson(path, -1);
        return getUUId(jsonNode);
    }

    /**
     * Get the UUID from a node that was already parsed in a {@link JsonNode}
     *
     * @param jsonNode {@link JsonNode} object of the repository node
     * @return UUID as String or null if jsonNode is null or if the UUID was not found
     * @throws ClientException if something fails during request/response cycle
     */
    // TODO make this method static
    public String getUUId(JsonNode jsonNode) throws ClientException {
        if (jsonNode == null) {
            return null;
        }

        JsonNode uuidNode = jsonNode.get("jcr:uuid");

        if (uuidNode == null) {
            return null;
        }

        return uuidNode.getValueAsText();
    }

    @Override
    public String getUser() {
        // get the username from the sudo cookie or default from client config
        return getCookieStore().getCookies().stream().filter(c -> c.getName().equals(getSudoCookieName())).findFirst()
                .map(c -> c.getValue().replace("\"", "")).orElse(super.getUser());
    }

    /**
     * Impersonate user with the given <code>userId</code>
     * <p>
     * By impersonating a user SlingClient can access content from that user eye view.
     * </p>
     *Passing a <code>null</code> will clear impersonation.
     *
     * @param userId   the user to impersonate. A <code>null</code> value clears impersonation
     */
    public SlingClient impersonate(String userId)  {
        BasicClientCookie c = new BasicClientCookie(getSudoCookieName(), "\"" + userId + "\"");
        c.setPath("/");
        c.setDomain(getUrl().getHost());
        if(userId == null || "-".equals(userId)){
            // setting expiry date in the past will remove the cookie
            c.setExpiryDate(new Date(0));
        }
        getCookieStore().addCookie(c);
        return this;
    }

    //
    // InternalBuilder class and builder related methods
    //

    /**
     * <p>Extensible InternalBuilder for SlingClient. Can be used by calling: {@code SlingClient.builder().create(...).build()}.
     * Between create() and build(), any number of <i>set</i> methods can be called to customize the client.<br>
     * It also exposes the underling httpClientBuilder through {@link #httpClientBuilder()} which can be used to customize the client
     * at http level.
     * </p>
     *
     * <p>The InternalBuilder is created to be easily extensible. A class, e.g. {@code MyClient extends SlingClient}, can have its own InternalBuilder.
     * This is worth creating if MyClient has fields that need to be initialized. The Skeleton of such InternalBuilder (created inside MyClient) is:
     * </p>
     * <blockquote><pre>
     * {@code
     * public static abstract class InternalBuilder<T extends MyClient> extends SlingClient.InternalBuilder<T> {
     *     private String additionalField;
     *
     *     public InternalBuilder(URI url, String user, String password) { super(url, user, password); }
     *
     *     public InternalBuilder<T> setAdditionalField(String s) { additionalField = s; }
     * }
     * }
     * </pre></blockquote>
     * <p>Besides this, two more methods need to be implemented directly inside {@code MyClient}: </p>
     * <blockquote><pre>
     * {@code
     * public static InternalBuilder<?> builder(URI url, String user, String password) {
     *     return new InternalBuilder<MyClient>(url, user, password) {
     *         {@literal @}Override
     *         public MyClient build() throws ClientException { return new MyClient(this); }
     *     };
     * }
     *
     * protected MyClient(InternalBuilder<MyClient> builder) throws ClientException {
     *   super(builder);
     *   additionalField = builder.additionalField;
     * }
     * }
     * </pre></blockquote>
     * Of course, the Clients and InternalBuilder are extensible on several levels, so MyClient.InternalBuilder can be further extended.
     *
     * @param <T> type extending SlingClient
     */
    public static abstract class InternalBuilder<T extends SlingClient> {

        private final SlingClientConfig.Builder configBuilder;

        private final HttpClientBuilder httpClientBuilder;

        protected InternalBuilder(URI url, String user, String password) {
            this.httpClientBuilder = HttpClientBuilder.create();
            this.configBuilder = SlingClientConfig.Builder.create().setUrl(url).setUser(user).setPassword(password);

            setDefaults();
        }

        public InternalBuilder<T> setUrl(URI url) {
            this.configBuilder.setUrl(url);
            return this;
        }

        public InternalBuilder<T> setUser(String user) {
            this.configBuilder.setUser(user);
            return this;
        }

        public InternalBuilder<T> setPassword(String password) {
            this.configBuilder.setPassword(password);
            return this;
        }

        public InternalBuilder<T> setCredentialsProvider(CredentialsProvider cp) {
            this.configBuilder.setCredentialsProvider(cp);
            return this;
        }

        public InternalBuilder<T> setPreemptiveAuth(boolean isPreemptiveAuth) {
            this.configBuilder.setPreemptiveAuth(isPreemptiveAuth);
            return this;
        }

        public InternalBuilder<T> setCookieStore(CookieStore cs) {
            this.configBuilder.setCookieStore(cs);
            return this;
        }

        public HttpClientBuilder httpClientBuilder() {
            return httpClientBuilder;
        }

        public abstract T build() throws ClientException;

        protected CloseableHttpClient buildHttpClient() {
            return httpClientBuilder.build();
        }

        protected SlingClientConfig buildSlingClientConfig() throws ClientException {
            return configBuilder.build();
        }

        /**
         * Sets defaults to the builder.
         *
         * @return this
         */
        private InternalBuilder setDefaults() {
            httpClientBuilder.useSystemProperties();
            httpClientBuilder.setUserAgent("Java");
            // Connection
            httpClientBuilder.setMaxConnPerRoute(10);
            httpClientBuilder.setMaxConnTotal(100);
            // Interceptors
            httpClientBuilder.addInterceptorLast(new TestDescriptionInterceptor());
            httpClientBuilder.addInterceptorLast(new DelayRequestInterceptor(SystemPropertiesConfig.getHttpDelay()));

            // HTTP request strategy
            httpClientBuilder.setServiceUnavailableRetryStrategy(new ServerErrorRetryStrategy());

            // connection timeouts
            int timeoutSeconds = TimeoutsProvider.getInstance().getTimeout(CLIENT_CONNECTION_TIMEOUT_PROP, -1);
            if (timeoutSeconds > 0) {
                int timeoutMs = (int)TimeUnit.SECONDS.toMillis(timeoutSeconds);
                RequestConfig config = RequestConfig.custom()
                        .setConnectTimeout(timeoutMs)
                        .setConnectionRequestTimeout(timeoutMs)
                        .setSocketTimeout(timeoutMs).build();
                this.httpClientBuilder.setDefaultRequestConfig(config);
            }

            return this;
        }

        //
        // HttpClientBuilder delegating methods
        //

        public final InternalBuilder<T> addInterceptorFirst(final HttpResponseInterceptor itcp) {
            httpClientBuilder.addInterceptorFirst(itcp);
            return this;
        }

        /**
         * Adds this protocol interceptor to the tail of the protocol processing list.
         * <p>
         * Please note this value can be overridden by the {@link HttpClientBuilder#setHttpProcessor(
         * org.apache.http.protocol.HttpProcessor)} method.
         * </p>
         *
         * @param itcp the interceptor
         * @return this
         */
        public final InternalBuilder<T> addInterceptorLast(final HttpResponseInterceptor itcp) {
            httpClientBuilder.addInterceptorLast(itcp);
            return this;
        }

        /**
         * Adds this protocol interceptor to the head of the protocol processing list.
         * <p>
         * Please note this value can be overridden by the {@link HttpClientBuilder#setHttpProcessor(
         * org.apache.http.protocol.HttpProcessor)} method.
         * </p>
         *
         * @param itcp the interceptor
         * @return this
         */
        public final InternalBuilder<T> addInterceptorFirst(final HttpRequestInterceptor itcp) {
            httpClientBuilder.addInterceptorFirst(itcp);
            return this;
        }

        /**
         * Adds this protocol interceptor to the tail of the protocol processing list.
         * <p>
         * Please note this value can be overridden by the {@link HttpClientBuilder#setHttpProcessor(
         * org.apache.http.protocol.HttpProcessor)} method.
         * </p>
         *
         * @param itcp the interceptor
         * @return this
         */
        public final InternalBuilder<T> addInterceptorLast(final HttpRequestInterceptor itcp) {
            httpClientBuilder.addInterceptorLast(itcp);
            return this;
        }

        /**
         * Adds this protocol interceptor to the head of the protocol processing list  for both requests and responses
         * <p>
         * Please note this value can be overridden by the {@link HttpClientBuilder#setHttpProcessor(
         * org.apache.http.protocol.HttpProcessor)} method.
         * </p>
         *
         * @param itcp the request and response interceptor
         * @return this
         */
        public final InternalBuilder<T> addInterceptorFirst(final HttpRequestResponseInterceptor itcp) {
            httpClientBuilder.addInterceptorFirst((HttpRequestInterceptor) itcp);
            httpClientBuilder.addInterceptorFirst((HttpResponseInterceptor) itcp);
            return this;
        }

        /**
         * Adds this protocol interceptor to the tail of the protocol processing list for both requests and responses
         * <p>
         * Please note this value can be overridden by the {@link HttpClientBuilder#setHttpProcessor(
         * org.apache.http.protocol.HttpProcessor)} method.
         * </p>
         *
         * @param itcp the request and response interceptor
         * @return this
         */
        public final InternalBuilder<T> addInterceptorLast(final HttpRequestResponseInterceptor itcp) {
            httpClientBuilder.addInterceptorLast((HttpRequestInterceptor) itcp);
            httpClientBuilder.addInterceptorLast((HttpResponseInterceptor) itcp);
            return this;
        }

        /**
         * Assigns {@link RedirectStrategy} instance.
         * <p>Please note this value can be overridden by the {@link #disableRedirectHandling()} method.</p>
         *
         * @param redirectStrategy custom redirect strategy
         * @return this
         */
        public final InternalBuilder<T> setRedirectStrategy(final RedirectStrategy redirectStrategy) {
            httpClientBuilder.setRedirectStrategy(redirectStrategy);
            return this;
        }

        /**
         * Disables automatic redirect handling.
         *
         * @return this
         */
        public final InternalBuilder<T> disableRedirectHandling() {
            httpClientBuilder.disableRedirectHandling();
            return this;
        }

    }

    public final static class Builder extends InternalBuilder<SlingClient> {

        private Builder(URI url, String user, String password) {
            super(url, user, password);
        }

        @Override
        public SlingClient build() throws ClientException {
            return new SlingClient(buildHttpClient(), buildSlingClientConfig());
        }

        public static Builder create(URI url, String user, String password) {
            return new Builder(url, user, password);
        }
    }
}
