// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.net;

import android.content.Context;
import android.text.TextUtils;

import org.apache.http.HttpStatus;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.ProtocolException;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.zip.GZIPInputStream;

/**
 * Network request using the HttpUrlConnection implementation.
 */
class HttpUrlConnectionUrlRequest implements HttpUrlRequest {

    private static final int MAX_CHUNK_SIZE = 8192;

    private static final int CONNECT_TIMEOUT = 3000;

    private static final int READ_TIMEOUT = 90000;

    private final Context mContext;

    private final String mUrl;

    private final Map<String, String> mHeaders;

    private final WritableByteChannel mSink;

    private final HttpUrlRequestListener mListener;

    private IOException mException;

    private HttpURLConnection mConnection;

    private long mOffset;

    private int mContentLength;

    private int mUploadContentLength;

    private long mContentLengthLimit;

    private boolean mCancelIfContentLengthOverLimit;

    private boolean mContentLengthOverLimit;

    private boolean mSkippingToOffset;

    private long mSize;

    private String mPostContentType;

    private byte[] mPostData;

    private ReadableByteChannel mPostDataChannel;

    private String mContentType;

    private int mHttpStatusCode;

    private boolean mStarted;

    private boolean mCanceled;

    private String mMethod;

    private InputStream mResponseStream;

    private final Object mLock;

    private static ExecutorService sExecutorService;

    private static final Object sExecutorServiceLock = new Object();

    HttpUrlConnectionUrlRequest(Context context, String url,
            int requestPriority, Map<String, String> headers,
            HttpUrlRequestListener listener) {
        this(context, url, requestPriority, headers,
                new ChunkedWritableByteChannel(), listener);
    }

    HttpUrlConnectionUrlRequest(Context context, String url,
            int requestPriority, Map<String, String> headers,
            WritableByteChannel sink, HttpUrlRequestListener listener) {
        if (context == null) {
            throw new NullPointerException("Context is required");
        }
        if (url == null) {
            throw new NullPointerException("URL is required");
        }
        mContext = context;
        mUrl = url;
        mHeaders = headers;
        mSink = sink;
        mListener = listener;
        mLock = new Object();
    }

    private static ExecutorService getExecutor() {
        synchronized (sExecutorServiceLock) {
            if (sExecutorService == null) {
                ThreadFactory threadFactory = new ThreadFactory() {
                    private final AtomicInteger mCount = new AtomicInteger(1);

                        @Override
                    public Thread newThread(Runnable r) {
                        Thread thread = new Thread(r,
                                "HttpUrlConnection #" +
                                mCount.getAndIncrement());
                        // Note that this thread is not doing actual networking.
                        // It's only a controller.
                        thread.setPriority(Thread.NORM_PRIORITY);
                        return thread;
                    }
                };
                sExecutorService = Executors.newCachedThreadPool(threadFactory);
            }
            return sExecutorService;
        }
    }

    @Override
    public String getUrl() {
        return mUrl;
    }

    @Override
    public void setOffset(long offset) {
        mOffset = offset;
    }

    @Override
    public void setContentLengthLimit(long limit, boolean cancelEarly) {
        mContentLengthLimit = limit;
        mCancelIfContentLengthOverLimit = cancelEarly;
    }

    @Override
    public void setUploadData(String contentType, byte[] data) {
        validateNotStarted();
        mPostContentType = contentType;
        mPostData = data;
        mPostDataChannel = null;
    }

    @Override
    public void setUploadChannel(String contentType,
            ReadableByteChannel channel, long contentLength) {
        validateNotStarted();
        if (contentLength > Integer.MAX_VALUE) {
            throw new IllegalArgumentException(
                "Upload contentLength is too big.");
        }
        mUploadContentLength = (int)contentLength;
        mPostContentType = contentType;
        mPostDataChannel = channel;
        mPostData = null;
    }


    @Override
    public void setHttpMethod(String method) {
        validateNotStarted();
        if (!("PUT".equals(method) || "POST".equals(method))) {
            throw new IllegalArgumentException(
                "Only PUT and POST are allowed.");
        }
        mMethod = method;
    }

    @Override
    public void start() {
        getExecutor().execute(new Runnable() {
            @Override
            public void run() {
                startOnExecutorThread();
            }
        });
    }

    private void startOnExecutorThread() {
        boolean readingResponse = false;
        try {
            synchronized (mLock) {
                if (mCanceled) {
                    return;
                }
            }

            URL url = new URL(mUrl);
            mConnection = (HttpURLConnection)url.openConnection();
            // If configured, use the provided http verb.
            if (mMethod != null) {
                try {
                    mConnection.setRequestMethod(mMethod);
                } catch (ProtocolException e) {
                    // Since request hasn't started earlier, it
                    // must be an illegal HTTP verb.
                    throw new IllegalArgumentException(e);
                }
            }
            mConnection.setConnectTimeout(CONNECT_TIMEOUT);
            mConnection.setReadTimeout(READ_TIMEOUT);
            mConnection.setInstanceFollowRedirects(true);
            if (mHeaders != null) {
                for (Entry<String, String> header : mHeaders.entrySet()) {
                    mConnection.setRequestProperty(header.getKey(),
                            header.getValue());
                }
            }

            if (mOffset != 0) {
                mConnection.setRequestProperty("Range",
                        "bytes=" + mOffset + "-");
            }

            if (mConnection.getRequestProperty("User-Agent") == null) {
                mConnection.setRequestProperty("User-Agent",
                        UserAgent.from(mContext));
            }

            if (mPostData != null || mPostDataChannel != null) {
                uploadData();
            }

            InputStream stream = null;
            try {
                // We need to open the stream before asking for the response
                // code.
                stream = mConnection.getInputStream();
            } catch (FileNotFoundException ex) {
                // Ignore - the response has no body.
            }

            mHttpStatusCode = mConnection.getResponseCode();
            mContentType = mConnection.getContentType();
            mContentLength = mConnection.getContentLength();
            if (mContentLengthLimit > 0 && mContentLength > mContentLengthLimit
                    && mCancelIfContentLengthOverLimit) {
                onContentLengthOverLimit();
                return;
            }

            mListener.onResponseStarted(this);

            mResponseStream = isError(mHttpStatusCode) ? mConnection
                    .getErrorStream()
                    : stream;

            if (mResponseStream != null
                    && "gzip".equals(mConnection.getContentEncoding())) {
                mResponseStream = new GZIPInputStream(mResponseStream);
                mContentLength = -1;
            }

            if (mOffset != 0) {
                // The server may ignore the request for a byte range.
                if (mHttpStatusCode == HttpStatus.SC_OK) {
                    if (mContentLength != -1) {
                        mContentLength -= mOffset;
                    }
                    mSkippingToOffset = true;
                } else {
                    mSize = mOffset;
                }
            }

            if (mResponseStream != null) {
                readingResponse = true;
                readResponseAsync();
            }
        } catch (IOException e) {
            mException = e;
        } finally {
            if (mPostDataChannel != null) {
                try {
                    mPostDataChannel.close();
                } catch (IOException e) {
                    // Ignore
                }
            }

            // Don't call onRequestComplete yet if we are reading the response
            // on a separate thread
            if (!readingResponse) {
                mListener.onRequestComplete(this);
            }
        }
    }

    private void uploadData() throws IOException {
        mConnection.setDoOutput(true);
        if (!TextUtils.isEmpty(mPostContentType)) {
            mConnection.setRequestProperty("Content-Type", mPostContentType);
        }

        OutputStream uploadStream = null;
        try {
            if (mPostData != null) {
                mConnection.setFixedLengthStreamingMode(mPostData.length);
                uploadStream = mConnection.getOutputStream();
                uploadStream.write(mPostData);
            } else {
                mConnection.setFixedLengthStreamingMode(mUploadContentLength);
                uploadStream = mConnection.getOutputStream();
                byte[] bytes = new byte[MAX_CHUNK_SIZE];
                ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
                while (mPostDataChannel.read(byteBuffer) > 0) {
                    byteBuffer.flip();
                    uploadStream.write(bytes, 0, byteBuffer.limit());
                    byteBuffer.clear();
                }
            }
        } finally {
            if (uploadStream != null) {
                uploadStream.close();
            }
        }
    }

    private void readResponseAsync() {
        getExecutor().execute(new Runnable() {
            @Override
            public void run() {
                readResponse();
            }
        });
    }

    private void readResponse() {
        try {
            if (mResponseStream != null) {
                readResponseStream();
            }
        } catch (IOException e) {
            mException = e;
        } finally {
            try {
                mConnection.disconnect();
            } catch (ArrayIndexOutOfBoundsException t) {
                // Ignore it.
            }

            try {
                mSink.close();
            } catch (IOException e) {
                if (mException == null) {
                    mException = e;
                }
            }
        }
        mListener.onRequestComplete(this);
    }

    private void readResponseStream() throws IOException {
        byte[] buffer = new byte[MAX_CHUNK_SIZE];
        int size;
        while (!isCanceled() && (size = mResponseStream.read(buffer)) != -1) {
            int start = 0;
            int count = size;
            mSize += size;
            if (mSkippingToOffset) {
                if (mSize <= mOffset) {
                    continue;
                } else {
                    mSkippingToOffset = false;
                    start = (int)(mOffset - (mSize - size));
                    count -= start;
                }
            }

            if (mContentLengthLimit != 0 && mSize > mContentLengthLimit) {
                count -= (int)(mSize - mContentLengthLimit);
                if (count > 0) {
                    mSink.write(ByteBuffer.wrap(buffer, start, count));
                }
                onContentLengthOverLimit();
                return;
            }

            mSink.write(ByteBuffer.wrap(buffer, start, count));
        }
    }

    @Override
    public void cancel() {
        synchronized (mLock) {
            if (mCanceled) {
                return;
            }

            mCanceled = true;
        }
    }

    @Override
    public boolean isCanceled() {
        synchronized (mLock) {
            return mCanceled;
        }
    }

    @Override
    public int getHttpStatusCode() {
        int httpStatusCode = mHttpStatusCode;

        // If we have been able to successfully resume a previously interrupted
        // download,
        // the status code will be 206, not 200. Since the rest of the
        // application is
        // expecting 200 to indicate success, we need to fake it.
        if (httpStatusCode == HttpStatus.SC_PARTIAL_CONTENT) {
            httpStatusCode = HttpStatus.SC_OK;
        }
        return httpStatusCode;
    }

    @Override
    public IOException getException() {
        if (mException == null && mContentLengthOverLimit) {
            mException = new ResponseTooLargeException();
        }
        return mException;
    }

    private void onContentLengthOverLimit() {
        mContentLengthOverLimit = true;
        cancel();
    }

    private static boolean isError(int statusCode) {
        return (statusCode / 100) != 2;
    }

    /**
     * Returns the response as a ByteBuffer.
     */
    @Override
    public ByteBuffer getByteBuffer() {
        return ((ChunkedWritableByteChannel)mSink).getByteBuffer();
    }

    @Override
    public byte[] getResponseAsBytes() {
        return ((ChunkedWritableByteChannel)mSink).getBytes();
    }

    @Override
    public long getContentLength() {
        return mContentLength;
    }

    @Override
    public String getContentType() {
        return mContentType;
    }


    @Override
    public String getHeader(String name) {
        if (mConnection == null) {
            throw new IllegalStateException("Response headers not available");
        }
        Map<String, List<String>> headerFields = mConnection.getHeaderFields();
        if (headerFields != null) {
            List<String> headerValues = headerFields.get(name);
            if (headerValues != null) {
                return TextUtils.join(", ", headerValues);
            }
        }
        return null;
    }

    private void validateNotStarted() {
        if (mStarted) {
            throw new IllegalStateException("Request already started");
        }
    }
}
