/*
 * Copyright 2011 Google 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 com.google.web.bindery.requestfactory.vm.testing;

import com.google.web.bindery.requestfactory.shared.RequestFactory;
import com.google.web.bindery.requestfactory.shared.RequestTransport;
import com.google.web.bindery.requestfactory.shared.ServerFailure;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpCookie;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.zip.GZIPInputStream;
import java.util.zip.InflaterInputStream;

/**
 * A trivial implementation of RequestTransport that uses a
 * {@link HttpURLConnection}. Details of the connection can be amended by
 * overriding {@link #configureConnection(HttpURLConnection)}.
 * <p>
 * This implementation only supports {@code http} and {@code https} URLs. It has
 * primitive support for recording and playing back cookies, but does not
 * implement expiration processing.
 * <p>
 * Developers who wish to build a more production-ready client should consider
 * using a RequestTRansport based around Apache HttpClient instead.
 */
public class UrlRequestTransport implements RequestTransport {
  private static final int CONNECT_TIMEOUT = 30000;
  private static final int READ_TIMEOUT = 60000;

  private final Map<String, String> cookies = new HashMap<String, String>();
  private final URL url;

  /**
   * Construct a new UrlRequestTransport.
   * 
   * @param url the URL to connect to
   * @throws IllegalArgumentException if the url's protocol is not {@code http}
   *           or {@code https}
   */
  public UrlRequestTransport(URL url) {
    this.url = url;
    String proto = url.getProtocol().toLowerCase(Locale.ROOT);
    if (!proto.equals("http") && !proto.equals("https")) {
      throw new IllegalArgumentException("Only http and https URLs supported");
    }
  }

  /**
   * Provides access to the cookies that will be sent for subsequent requests.
   */
  public Map<String, String> getCookies() {
    return cookies;
  }

  @Override
  public void send(String payload, TransportReceiver receiver) {
    HttpURLConnection connection = null;
    try {
      connection = (HttpURLConnection) url.openConnection();
      configureConnection(connection);

      OutputStream out = connection.getOutputStream();
      out.write(payload.getBytes("UTF-8"));
      out.close();

      int status = connection.getResponseCode();
      if (status != HttpURLConnection.HTTP_OK) {
        ServerFailure failure = new ServerFailure(status + " " + connection.getResponseMessage());
        receiver.onTransportFailure(failure);
        return;
      }

      List<String> cookieHeaders = connection.getHeaderFields().get("Set-Cookie");
      if (cookieHeaders != null) {
        for (String header : cookieHeaders) {
          List<HttpCookie> headerCookies;
          try {
            headerCookies = HttpCookie.parse(header);
          } catch (IllegalArgumentException e) {
            // if we can't parse it, ignore it
            continue;
          }

          for (HttpCookie cookie : headerCookies) {
            String domain = cookie.getDomain();
            if (domain == null || url.getHost().endsWith(domain)) {
              String path = cookie.getPath();
              if (path == null || url.getPath().startsWith(path)) {
                cookies.put(cookie.getName(), cookie.getValue());
              }
            }
          }
        }
      }

      String encoding = connection.getContentEncoding();
      InputStream in = connection.getInputStream();
      if ("gzip".equalsIgnoreCase(encoding)) {
        in = new GZIPInputStream(in);
      } else if ("deflate".equalsIgnoreCase(encoding)) {
        in = new InflaterInputStream(in);
      } else if (encoding != null) {
        receiver.onTransportFailure(new ServerFailure("Unknown server encoding " + encoding));
        return;
      }

      ByteArrayOutputStream bytes = new ByteArrayOutputStream();
      byte[] buffer = new byte[4096];
      int read = in.read(buffer);
      while (read != -1) {
        bytes.write(buffer, 0, read);
        read = in.read(buffer);
      }
      in.close();

      String received = new String(bytes.toByteArray(), "UTF-8");
      receiver.onTransportSuccess(received);
    } catch (IOException e) {
      ServerFailure failure = new ServerFailure(e.getMessage(), e.getClass().getName(), null, true);
      receiver.onTransportFailure(failure);
    } finally {
      if (connection != null) {
        connection.disconnect();
      }
    }
  }

  protected void configureConnection(HttpURLConnection connection) throws IOException {
    connection.setDoInput(true);
    connection.setDoOutput(true);
    connection.setRequestMethod("POST");
    connection.setUseCaches(false);
    connection.setRequestProperty("Accept-Encoding", "gzip, deflate");
    connection.setRequestProperty("Content-Type", RequestFactory.JSON_CONTENT_TYPE_UTF8);
    connection.setRequestProperty("Host", url.getHost());
    connection.setRequestProperty("User-Agent", UrlRequestTransport.class.getCanonicalName());
    connection.setConnectTimeout(CONNECT_TIMEOUT);
    connection.setReadTimeout(READ_TIMEOUT);

    if (!cookies.isEmpty()) {
      StringBuilder sb = new StringBuilder();
      boolean needsSemi = false;
      for (Map.Entry<String, String> entry : cookies.entrySet()) {
        if (needsSemi) {
          sb.append("; ");
        } else {
          needsSemi = true;
        }
        sb.append(entry.getKey()).append("=").append(entry.getValue());
      }
      connection.setRequestProperty("Cookie", sb.toString());
    }
  }
}
