/*
 * Copyright 2008 Netflix, Inc.
 *
 * Licensed 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 net.oauth.client;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import net.oauth.http.HttpClient;
import net.oauth.http.HttpMessage;
import net.oauth.http.HttpResponseMessage;

/**
 * An HttpClient based on HttpURLConnection.
 * <p>
 * HttpClient3 or HttpClient4 perform better than this class, as a rule; since
 * they do things like connection pooling.  They also support reading the body
 * of an HTTP response whose status code isn't 200 (OK), which can enable your
 * application to handle problems better.
 * 
 * @author John Kristian
 * @hide
 */
public class URLConnectionClient implements HttpClient {

    /** Send a message to the service provider and get the response. */
    public HttpResponseMessage execute(HttpMessage request) throws IOException {
        final String httpMethod = request.method;
        final Collection<Map.Entry<String, String>> addHeaders = request.headers;
        final URL url = request.url;
        final URLConnection connection = url.openConnection();
        connection.setDoInput(true);
        if (connection instanceof HttpURLConnection) {
            HttpURLConnection http = (HttpURLConnection) connection;
            http.setRequestMethod(httpMethod);
            http.setInstanceFollowRedirects(false);
        }
        StringBuilder headers = new StringBuilder(httpMethod);
        {
            headers.append(" ").append(url.getPath());
            String query = url.getQuery();
            if (query != null && query.length() > 0) {
                headers.append("?").append(query);
            }
            headers.append(EOL);
            for (Map.Entry<String, List<String>> header : connection
                    .getRequestProperties().entrySet()) {
                String key = header.getKey();
                for (String value : header.getValue()) {
                    headers.append(key).append(": ").append(value).append(EOL);
                }
            }
        }
        String contentLength = null;
        for (Map.Entry<String, String> header : addHeaders) {
            String key = header.getKey();
            if (HttpMessage.CONTENT_LENGTH.equalsIgnoreCase(key)
                    && connection instanceof HttpURLConnection) {
                contentLength = header.getValue();
            } else {
                connection.setRequestProperty(key, header.getValue());
            }
            headers.append(key).append(": ").append(header.getValue()).append(EOL);
        }
        byte[] excerpt = null;
        final InputStream body = request.getBody();
        if (body != null) {
            try {
                if (contentLength != null) {
                    ((HttpURLConnection) connection)
                    .setFixedLengthStreamingMode(Integer.parseInt(contentLength));
                }
                connection.setDoOutput(true);
                OutputStream output = connection.getOutputStream();
                try {
                    final ExcerptInputStream ex = new ExcerptInputStream(body);
                    byte[] b = new byte[1024];
                    for (int n; 0 < (n = ex.read(b));) {
                        output.write(b, 0, n);
                    }
                    excerpt = ex.getExcerpt();
                } finally {
                    output.close();
                }
            } finally {
                body.close();
            }
        }
        return new URLConnectionResponse(request, headers.toString(), excerpt, connection);
    }

    private static final String EOL = HttpResponseMessage.EOL;

}
