//
//  ========================================================================
//  Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
//  ------------------------------------------------------------------------
//  All rights reserved. This program and the accompanying materials
//  are made available under the terms of the Eclipse Public License v1.0
//  and Apache License v2.0 which accompanies this distribution.
//
//      The Eclipse Public License is available at
//      http://www.eclipse.org/legal/epl-v10.html
//
//      The Apache License v2.0 is available at
//      http://www.opensource.org/licenses/apache2.0.php
//
//  You may elect to redistribute this code under either of these licenses.
//  ========================================================================
//

package org.eclipse.jetty.client;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.HttpCookie;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.ByteBuffer;
import java.nio.charset.UnsupportedCharsetException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicReference;

import org.eclipse.jetty.client.api.ContentProvider;
import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.client.api.Result;
import org.eclipse.jetty.client.util.FutureResponseListener;
import org.eclipse.jetty.client.util.PathContentProvider;
import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.Fields;

public class HttpRequest implements Request
{
    private static final URI NULL_URI = URI.create("null:0");

    private final HttpFields headers = new HttpFields();
    private final Fields params = new Fields(true);
    private final List<Response.ResponseListener> responseListeners = new ArrayList<>();
    private final AtomicReference<Throwable> aborted = new AtomicReference<>();
    private final HttpClient client;
    private final HttpConversation conversation;
    private final String host;
    private final int port;
    private URI uri;
    private String scheme;
    private String path;
    private String query;
    private String method = HttpMethod.GET.asString();
    private HttpVersion version = HttpVersion.HTTP_1_1;
    private long idleTimeout;
    private long timeout;
    private ContentProvider content;
    private boolean followRedirects;
    private List<HttpCookie> cookies;
    private Map<String, Object> attributes;
    private List<RequestListener> requestListeners;

    protected HttpRequest(HttpClient client, HttpConversation conversation, URI uri)
    {
        this.client = client;
        this.conversation = conversation;
        scheme = uri.getScheme();
        host = client.normalizeHost(uri.getHost());
        port = HttpClient.normalizePort(scheme, uri.getPort());
        path = uri.getRawPath();
        query = uri.getRawQuery();
        extractParams(query);
        followRedirects(client.isFollowRedirects());
        idleTimeout = client.getIdleTimeout();
        HttpField acceptEncodingField = client.getAcceptEncodingField();
        if (acceptEncodingField != null)
            headers.put(acceptEncodingField);
        HttpField userAgentField = client.getUserAgentField();
        if (userAgentField != null)
            headers.put(userAgentField);
    }

    protected HttpConversation getConversation()
    {
        return conversation;
    }

    @Override
    public String getScheme()
    {
        return scheme;
    }

    @Override
    public Request scheme(String scheme)
    {
        this.scheme = scheme;
        this.uri = null;
        return this;
    }

    @Override
    public String getHost()
    {
        return host;
    }

    @Override
    public int getPort()
    {
        return port;
    }

    @Override
    public String getMethod()
    {
        return method;
    }

    @Override
    public Request method(HttpMethod method)
    {
        return method(method.asString());
    }

    @Override
    public Request method(String method)
    {
        this.method = Objects.requireNonNull(method).toUpperCase(Locale.ENGLISH);
        return this;
    }

    @Override
    public String getPath()
    {
        return path;
    }

    @Override
    public Request path(String path)
    {
        URI uri = newURI(path);
        if (uri == null)
        {
            this.path = path;
            this.query = null;
        }
        else
        {
            String rawPath = uri.getRawPath();
            if (uri.isOpaque())
                rawPath = path;
            if (rawPath == null)
                rawPath = "";
            this.path = rawPath;
            String query = uri.getRawQuery();
            if (query != null)
            {
                this.query = query;
                params.clear();
                extractParams(query);
            }
            if (uri.isAbsolute())
                this.path = buildURI(false).toString();
        }
        this.uri = null;
        return this;
    }

    @Override
    public String getQuery()
    {
        return query;
    }

    @Override
    public URI getURI()
    {
        if (uri == null)
            uri = buildURI(true);
        return uri == NULL_URI ? null : uri;
    }

    @Override
    public HttpVersion getVersion()
    {
        return version;
    }

    @Override
    public Request version(HttpVersion version)
    {
        this.version = Objects.requireNonNull(version);
        return this;
    }

    @Override
    public Request param(String name, String value)
    {
        return param(name, value, false);
    }

    private Request param(String name, String value, boolean fromQuery)
    {
        params.add(name, value);
        if (!fromQuery)
        {
            // If we have an existing query string, preserve it and append the new parameter.
            if (query != null)
                query += "&" + urlEncode(name) + "=" + urlEncode(value);
            else
                query = buildQuery();
            uri = null;
        }
        return this;
    }

    @Override
    public Fields getParams()
    {
        return new Fields(params, true);
    }

    @Override
    public String getAgent()
    {
        return headers.get(HttpHeader.USER_AGENT);
    }

    @Override
    public Request agent(String agent)
    {
        headers.put(HttpHeader.USER_AGENT, agent);
        return this;
    }

    @Override
    public Request accept(String... accepts)
    {
        StringBuilder result = new StringBuilder();
        for (String accept : accepts)
        {
            if (result.length() > 0)
                result.append(", ");
            result.append(accept);
        }
        if (result.length() > 0)
            headers.put(HttpHeader.ACCEPT, result.toString());
        return this;
    }

    @Override
    public Request header(String name, String value)
    {
        if (value == null)
            headers.remove(name);
        else
            headers.add(name, value);
        return this;
    }

    @Override
    public Request header(HttpHeader header, String value)
    {
        if (value == null)
            headers.remove(header);
        else
            headers.add(header, value);
        return this;
    }

    @Override
    public List<HttpCookie> getCookies()
    {
        return cookies != null ? cookies : Collections.<HttpCookie>emptyList();
    }

    @Override
    public Request cookie(HttpCookie cookie)
    {
        if (cookies == null)
            cookies = new ArrayList<>();
        cookies.add(cookie);
        return this;
    }

    @Override
    public Request attribute(String name, Object value)
    {
        if (attributes == null)
            attributes = new HashMap<>(4);
        attributes.put(name, value);
        return this;
    }

    @Override
    public Map<String, Object> getAttributes()
    {
        return attributes != null ? attributes : Collections.<String, Object>emptyMap();
    }

    @Override
    public HttpFields getHeaders()
    {
        return headers;
    }

    @Override
    @SuppressWarnings("unchecked")
    public <T extends RequestListener> List<T> getRequestListeners(Class<T> type)
    {
        // This method is invoked often in a request/response conversation,
        // so we avoid allocation if there is no need to filter.
        if (type == null || requestListeners == null)
            return requestListeners != null ? (List<T>)requestListeners : Collections.<T>emptyList();

        ArrayList<T> result = new ArrayList<>();
        for (RequestListener listener : requestListeners)
            if (type.isInstance(listener))
                result.add((T)listener);
        return result;
    }

    @Override
    public Request listener(Request.Listener listener)
    {
        return requestListener(listener);
    }

    @Override
    public Request onRequestQueued(final QueuedListener listener)
    {
        return requestListener(new QueuedListener()
        {
            @Override
            public void onQueued(Request request)
            {
                listener.onQueued(request);
            }
        });
    }

    @Override
    public Request onRequestBegin(final BeginListener listener)
    {
        return requestListener(new BeginListener()
        {
            @Override
            public void onBegin(Request request)
            {
                listener.onBegin(request);
            }
        });
    }

    @Override
    public Request onRequestHeaders(final HeadersListener listener)
    {
        return requestListener(new HeadersListener()
        {
            @Override
            public void onHeaders(Request request)
            {
                listener.onHeaders(request);
            }
        });
    }

    @Override
    public Request onRequestCommit(final CommitListener listener)
    {
        return requestListener(new CommitListener()
        {
            @Override
            public void onCommit(Request request)
            {
                listener.onCommit(request);
            }
        });
    }

    @Override
    public Request onRequestContent(final ContentListener listener)
    {
        return requestListener(new ContentListener()
        {
            @Override
            public void onContent(Request request, ByteBuffer content)
            {
                listener.onContent(request, content);
            }
        });
    }

    @Override
    public Request onRequestSuccess(final SuccessListener listener)
    {
        return requestListener(new SuccessListener()
        {
            @Override
            public void onSuccess(Request request)
            {
                listener.onSuccess(request);
            }
        });
    }

    @Override
    public Request onRequestFailure(final FailureListener listener)
    {
        return requestListener(new FailureListener()
        {
            @Override
            public void onFailure(Request request, Throwable failure)
            {
                listener.onFailure(request, failure);
            }
        });
    }

    private Request requestListener(RequestListener listener)
    {
        if (requestListeners == null)
            requestListeners = new ArrayList<>();
        requestListeners.add(listener);
        return this;
    }

    @Override
    public Request onResponseBegin(final Response.BeginListener listener)
    {
        this.responseListeners.add(new Response.BeginListener()
        {
            @Override
            public void onBegin(Response response)
            {
                listener.onBegin(response);
            }
        });
        return this;
    }

    @Override
    public Request onResponseHeader(final Response.HeaderListener listener)
    {
        this.responseListeners.add(new Response.HeaderListener()
        {
            @Override
            public boolean onHeader(Response response, HttpField field)
            {
                return listener.onHeader(response, field);
            }
        });
        return this;
    }

    @Override
    public Request onResponseHeaders(final Response.HeadersListener listener)
    {
        this.responseListeners.add(new Response.HeadersListener()
        {
            @Override
            public void onHeaders(Response response)
            {
                listener.onHeaders(response);
            }
        });
        return this;
    }

    @Override
    public Request onResponseContent(final Response.ContentListener listener)
    {
        this.responseListeners.add(new Response.AsyncContentListener()
        {
            @Override
            public void onContent(Response response, ByteBuffer content, Callback callback)
            {
                try
                {
                    listener.onContent(response, content);
                    callback.succeeded();
                }
                catch (Exception x)
                {
                    callback.failed(x);
                }
            }
        });
        return this;
    }

    @Override
    public Request onResponseContentAsync(final Response.AsyncContentListener listener)
    {
        this.responseListeners.add(new Response.AsyncContentListener()
        {
            @Override
            public void onContent(Response response, ByteBuffer content, Callback callback)
            {
                listener.onContent(response, content, callback);
            }
        });
        return this;
    }

    @Override
    public Request onResponseSuccess(final Response.SuccessListener listener)
    {
        this.responseListeners.add(new Response.SuccessListener()
        {
            @Override
            public void onSuccess(Response response)
            {
                listener.onSuccess(response);
            }
        });
        return this;
    }

    @Override
    public Request onResponseFailure(final Response.FailureListener listener)
    {
        this.responseListeners.add(new Response.FailureListener()
        {
            @Override
            public void onFailure(Response response, Throwable failure)
            {
                listener.onFailure(response, failure);
            }
        });
        return this;
    }

    @Override
    public Request onComplete(final Response.CompleteListener listener)
    {
        this.responseListeners.add(new Response.CompleteListener()
        {
            @Override
            public void onComplete(Result result)
            {
                listener.onComplete(result);
            }
        });
        return this;
    }

    @Override
    public ContentProvider getContent()
    {
        return content;
    }

    @Override
    public Request content(ContentProvider content)
    {
        return content(content, null);
    }

    @Override
    public Request content(ContentProvider content, String contentType)
    {
        if (contentType != null)
            header(HttpHeader.CONTENT_TYPE, contentType);
        this.content = content;
        return this;
    }

    @Override
    public Request file(Path file) throws IOException
    {
        return file(file, "application/octet-stream");
    }

    @Override
    public Request file(Path file, String contentType) throws IOException
    {
        return content(new PathContentProvider(contentType, file));
    }

    @Override
    public boolean isFollowRedirects()
    {
        return followRedirects;
    }

    @Override
    public Request followRedirects(boolean follow)
    {
        this.followRedirects = follow;
        return this;
    }

    @Override
    public long getIdleTimeout()
    {
        return idleTimeout;
    }

    @Override
    public Request idleTimeout(long timeout, TimeUnit unit)
    {
        this.idleTimeout = unit.toMillis(timeout);
        return this;
    }

    @Override
    public long getTimeout()
    {
        return timeout;
    }

    @Override
    public Request timeout(long timeout, TimeUnit unit)
    {
        this.timeout = unit.toMillis(timeout);
        return this;
    }

    @Override
    public ContentResponse send() throws InterruptedException, TimeoutException, ExecutionException
    {
        FutureResponseListener listener = new FutureResponseListener(this);
        send(this, listener);

        try
        {
            long timeout = getTimeout();
            if (timeout <= 0)
                return listener.get();

            return listener.get(timeout, TimeUnit.MILLISECONDS);
        }
        catch (Throwable x)
        {
            // Differently from the Future, the semantic of this method is that if
            // the send() is interrupted or times out, we abort the request.
            abort(x);
            throw x;
        }
    }

    @Override
    public void send(Response.CompleteListener listener)
    {
        TimeoutCompleteListener timeoutListener = null;
        try
        {
            if (getTimeout() > 0)
            {
                timeoutListener = new TimeoutCompleteListener(this);
                timeoutListener.schedule(client.getScheduler());
                responseListeners.add(timeoutListener);
            }
            send(this, listener);
        }
        catch (Throwable x)
        {
            // Do not leak the scheduler task if we
            // can't even start sending the request.
            if (timeoutListener != null)
                timeoutListener.cancel();
            throw x;
        }
    }

    private void send(HttpRequest request, Response.CompleteListener listener)
    {
        if (listener != null)
            responseListeners.add(listener);
        client.send(request, responseListeners);
    }

    @Override
    public boolean abort(Throwable cause)
    {
        if (aborted.compareAndSet(null, Objects.requireNonNull(cause)))
        {
            if (content instanceof Callback)
                ((Callback)content).failed(cause);
            return conversation.abort(cause);
        }
        return false;
    }

    @Override
    public Throwable getAbortCause()
    {
        return aborted.get();
    }

    private String buildQuery()
    {
        StringBuilder result = new StringBuilder();
        for (Iterator<Fields.Field> iterator = params.iterator(); iterator.hasNext(); )
        {
            Fields.Field field = iterator.next();
            List<String> values = field.getValues();
            for (int i = 0; i < values.size(); ++i)
            {
                if (i > 0)
                    result.append("&");
                result.append(field.getName()).append("=");
                result.append(urlEncode(values.get(i)));
            }
            if (iterator.hasNext())
                result.append("&");
        }
        return result.toString();
    }

    private String urlEncode(String value)
    {
        if (value == null)
            return "";

        String encoding = "UTF-8";
        try
        {
            return URLEncoder.encode(value, encoding);
        }
        catch (UnsupportedEncodingException e)
        {
            throw new UnsupportedCharsetException(encoding);
        }
    }

    private void extractParams(String query)
    {
        if (query != null)
        {
            for (String nameValue : query.split("&"))
            {
                String[] parts = nameValue.split("=");
                if (parts.length > 0)
                {
                    String name = urlDecode(parts[0]);
                    if (name.trim().length() == 0)
                        continue;
                    param(name, parts.length < 2 ? "" : urlDecode(parts[1]), true);
                }
            }
        }
    }

    private String urlDecode(String value)
    {
        String charset = "UTF-8";
        try
        {
            return URLDecoder.decode(value, charset);
        }
        catch (UnsupportedEncodingException x)
        {
            throw new UnsupportedCharsetException(charset);
        }
    }

    private URI buildURI(boolean withQuery)
    {
        String path = getPath();
        String query = getQuery();
        if (query != null && withQuery)
            path += "?" + query;
        URI result = newURI(path);
        if (result == null)
            return NULL_URI;
        if (!result.isAbsolute() && !result.isOpaque())
            result = URI.create(new Origin(getScheme(), getHost(), getPort()).asString() + path);
        return result;
    }

    private URI newURI(String uri)
    {
        try
        {
            return new URI(uri);
        }
        catch (URISyntaxException x)
        {
            // The "path" of a HTTP request may not be a URI,
            // for example for CONNECT 127.0.0.1:8080 or OPTIONS *.
            return null;
        }
    }

    @Override
    public String toString()
    {
        return String.format("%s[%s %s %s]@%x", HttpRequest.class.getSimpleName(), getMethod(), getPath(), getVersion(), hashCode());
    }
}
