/*
 * 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.gwt.core.shared.impl.StringCase;
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.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 = StringCase.toLower(url.getProtocol());
    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());
    }
  }
}
