// 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.its.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.nio.charset.StandardCharsets;
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 com.google.gson.Gson;
import com.google.gson.JsonObject;

import com.googlesource.gerrit.plugins.its.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(), StandardCharsets.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(), StandardCharsets.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, StandardCharsets.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;
  }
}
