// 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 com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.googlesource.gerrit.plugins.its.rtc.api.ResourceNotFoundException;
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;

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<>();

  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) {
    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) {
    HttpGet get = new HttpGet(toUri(path));
    get.setParams(httpParams);
    return get;
  }

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

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

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