// Copyright (C) 2013 The Android Open Source Project
//
// 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.googlesource.gerrit.plugins.hooks.rtc.network;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.net.MalformedURLException;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.List;

import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HTTP;

import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.googlesource.gerrit.plugins.hooks.rtc.api.ResourceNotFoundException;

public class Transport {

  public static final String APP_JSON = "application/json";
  public static final String ANY = "*/*";
  public static final String APP_OSLC =
      "application/x-oslc-cm-change-request+json";

  private static final Log log = LogFactory.getLog(Transport.class);

  public static final ThreadLocal<String> etag = new ThreadLocal<String>();

  protected HttpClient httpclient;
  protected Gson gson;
  protected String baseUrl;
  private HttpParams httpParams;
  private RTCClient rtcClient;

  public Transport(RTCClient rtcClient, String baseUrl, DefaultHttpClient httpclient, HttpParams httpParams) {
    this.rtcClient = rtcClient;
    this.baseUrl = baseUrl;
    this.httpclient = httpclient;
    this.httpParams = httpParams;
  }

  public void setGson(Gson gson) {
    this.gson = gson;
  }

  public <T> T put(final String path, final Type typeOrClass, JsonObject data,
      String etag) throws IOException {
    HttpPut request = new HttpPut(toUri(path));
    if (log.isDebugEnabled())
      log.debug("Preparing PUT against " + request.getURI() + " using etag "
          + etag + " and data " + data);
    request.setEntity(new StringEntity(data.toString(), HTTP.UTF_8));
    if (etag != null) request.addHeader("If-Match", etag);
    return invoke(request, typeOrClass, APP_OSLC, APP_OSLC);
  }

  public <T> T patch(final String path, final Type typeOrClass,
      JsonObject data, String etag) throws IOException {
    HttpPatch request = newHttpPatch(path);
    if (log.isDebugEnabled())
      log.debug("Preparing PATCH against " + request.getURI() + " using etag "
          + etag + " and data " + data);
    request.setEntity(new StringEntity(data.toString(), HTTP.UTF_8));
    if (etag != null) request.addHeader("If-Match", etag);
    return invoke(request, typeOrClass, APP_OSLC, APP_OSLC);
  }

  public <T> T post(final String path, final Type typeOrClass,
      String contentType,
      final NameValuePair... params) throws IOException {
    HttpPost request = newHttpPost(path);
    if (log.isDebugEnabled())
      log.debug("Preparing POST against " + request.getURI() + " using params "
          + Arrays.asList(params));
    List<NameValuePair> nameValuePairs = Arrays.asList(params);
    request.setEntity(new UrlEncodedFormEntity(nameValuePairs, HTTP.UTF_8));
    return invoke(request, typeOrClass, contentType, null);
  }

  public <T> T get(final String path, final Type typeOrClass)
      throws IOException, MalformedURLException {
    final HttpGet request = newHttpGet(path);
    if (log.isDebugEnabled())
      log.debug("Preparing GET against " + request.getURI());
    return invoke(request, typeOrClass, APP_JSON, null);
  }

  public String get(final String path) throws IOException,
      MalformedURLException {
    final HttpGet request = newHttpGet(path);
    if (log.isDebugEnabled())
      log.debug("Preparing GET against " + request.getURI());
    return invoke(request, null, ANY, null);
  }

  @SuppressWarnings("unchecked")
  private synchronized <T> T invoke(HttpRequestBase request,
      Object typeOrClass, String acceptType, String contentType)
      throws IOException, ClientProtocolException, ResourceNotFoundException {

    if (contentType != null) {
      request.addHeader("Content-Type", contentType);
    }

    if (acceptType != null) {
      request.addHeader("Accept", acceptType);
    }

    HttpResponse response = httpclient.execute(request);
    try {
      final int code = response.getStatusLine().getStatusCode();
      if (code / 100 != 2) {
        if (code == 404) {
          log.debug("API call failed: " + response.getStatusLine());
          throw new ResourceNotFoundException(request.getURI());
        } else {
          log.debug("API call failed: " + response.getStatusLine());
          throw new IOException("API call failed! " + response.getStatusLine());
        }
      }

      String responseContentTypeString = getResponseContentType(response);
      String entityString = readEntityAsString(response);

      if (!assertValidContentType(acceptType, responseContentTypeString)) {
        log.error("Request to " + request.getURI()
            + " failed because of an invalid content returned:\n"
            + entityString);
        rtcClient.setLoggedIn(false);
        throw new InvalidContentTypeException("Wrong content type '"
            + responseContentTypeString + "' in HTTP response (Expected: "
            + acceptType + ")");
      }

      if (typeOrClass != null && acceptType.endsWith("json")
          && responseContentTypeString.endsWith("json")) {
        Transport.etag.set(extractEtag(response));
        if (typeOrClass instanceof ParameterizedType) {
          return gson.fromJson(entityString, (Type) typeOrClass);
        } else {
          return gson.fromJson(entityString, (Class<T>) typeOrClass);
        }
      } else if (typeOrClass != null && typeOrClass.equals(String.class)) {
        return (T) entityString;
      } else {
        if (log.isDebugEnabled()) log.debug(entityString);
        return null;
      }
    } finally {
      consumeHttpEntity(response.getEntity());
      Transport.etag.set(null);
    }
  }

  private boolean assertValidContentType(String acceptType,
      String responseContentTypeString) throws IOException {
    if (acceptType == null) {
      return true;
    }
    if (acceptType.endsWith("/*")) {
      return true;
    }
    if (acceptType.split("/")[1].equalsIgnoreCase(responseContentTypeString
        .split("/")[1])) {
      return true;
    }
    return false;
  }

  public String getResponseContentType(HttpResponse response) {
    Header contentType = response.getEntity().getContentType();
    if (contentType == null) {
      return null;
    }

    String contentTypeValue = contentType.getValue();
    if (contentTypeValue == null) {
      return null;
    }

    for (String contentTypeItem : contentTypeValue.split(";")) {
      if (contentTypeItem.indexOf('/') >= 0) {
        return contentTypeItem;
      }
    }
    return null;
  }

  private String readEntityAsString(HttpResponse response)
      throws IllegalStateException, IOException {
    String charset = "utf-8";
    Header[] contentTypes = response.getHeaders("Content-Type");
    for (Header header : contentTypes) {
      if (header.getName().equalsIgnoreCase("charset")) {
        charset = header.getValue();
      }
    }

    ByteArrayOutputStream responseOut = new ByteArrayOutputStream();
    try {
      IOUtils.copy(response.getEntity().getContent(), responseOut);
    } finally {
      responseOut.close();
    }

    return new String(responseOut.toByteArray(), Charset.forName(charset));
  }

  // We can't use the HTTP Client 4.2 EntityUtils.consume()
  // because of compatibility issues with gerrit-pgm 2.5
  // that includes httpclient 4.0
  private void consumeHttpEntity(final HttpEntity entity) throws IOException {
    if (entity == null) {
      return;
    }
    if (entity.isStreaming()) {
      InputStream instream = entity.getContent();
      if (instream != null) {
        instream.close();
      }
    }
  }

  private String extractEtag(HttpResponse response) {
    final Header etagHeader = response.getFirstHeader("ETag");
    return etagHeader == null ? null : etagHeader.getValue().substring(1,
        etagHeader.getValue().length() - 1);
  }

  private HttpGet newHttpGet(final String path) throws MalformedURLException {
    HttpGet get = new HttpGet(toUri(path));
    get.setParams(httpParams);
    return get;
  }

  private HttpPost newHttpPost(final String path) throws MalformedURLException {
    return new HttpPost(toUri(path));
  }

  private HttpPatch newHttpPatch(final String path)
      throws MalformedURLException {
    return new HttpPatch(toUri(path));
  }

  private String toUri(final String path) throws MalformedURLException {
    if (path.startsWith(baseUrl))
      return path;
    else
      return baseUrl + path;
  }
}
