// Copyright (C) 2017 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.phabricator.conduit;

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.googlesource.gerrit.plugins.its.phabricator.conduit.results.CallCapsule;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/** Abstracts the connection to Conduit API */
class ConduitConnection {
  private static final Logger log = LoggerFactory.getLogger(Conduit.class);

  private final String apiUrlBase;
  private final Gson gson;

  private CloseableHttpClient client;

  ConduitConnection(final String baseUrl) {
    apiUrlBase = baseUrl.replaceAll("/+$", "") + "/api/";
    gson = new Gson();
    client = null;
  }

  /**
   * Gives a cached HttpClient
   *
   * <p>If no cached HttpClient exists, a new one is spawned.
   *
   * @return the cached CloseableHttpClient
   */
  private CloseableHttpClient getClient() {
    if (client == null) {
      log.trace("Creating new client connection");
      client = HttpClients.createDefault();
    }
    return client;
  }

  /**
   * Call the given Conduit method without parameters
   *
   * @param method The name of the method that should get called
   * @return The call's result, if there has been no error
   * @throws ConduitException
   */
  JsonElement call(String method, String token) throws ConduitException {
    return call(method, new HashMap<String, Object>(), token);
  }

  /**
   * Calls a conduit method with some parameters
   *
   * @param method The name of the method that should get called
   * @param params A map of parameters to pass to the call
   * @return The call's result, if there has been no error
   * @throws ConduitException
   */
  JsonElement call(String method, Map<String, Object> params, String token)
      throws ConduitException {
    String methodUrl = apiUrlBase + method;

    HttpPost httppost = new HttpPost(methodUrl);

    if (token != null) {
      Map<String, Object> conduitParams = new HashMap<>();
      conduitParams.put("token", token);
      params.put("__conduit__", conduitParams);
    }

    String json = gson.toJson(params);

    log.trace("Calling phabricator method " + method + " with the parameters " + json);
    httppost.setEntity(new StringEntity("params=" + json, StandardCharsets.UTF_8));

    CloseableHttpResponse response;
    try {
      response = getClient().execute(httppost);
    } catch (IOException e) {
      throw new ConduitException("Could not execute Phabricator API call", e);
    }
    try {
      log.trace("Phabricator HTTP response status: " + response.getStatusLine());
      HttpEntity entity = response.getEntity();
      String entityString;
      try {
        entityString = EntityUtils.toString(entity);
      } catch (IOException e) {
        throw new ConduitException("Could not read the API response", e);
      }

      log.trace("Phabricator response " + entityString);
      CallCapsule callCapsule = gson.fromJson(entityString, CallCapsule.class);
      log.trace("callCapsule.result: " + callCapsule.getResult());
      log.trace("callCapsule.error_code: " + callCapsule.getErrorCode());
      log.trace("callCapsule.error_info: " + callCapsule.getErrorInfo());
      if (callCapsule.getErrorCode() != null || callCapsule.getErrorInfo() != null) {
        throw new ConduitErrorException(
            method, callCapsule.getErrorCode(), callCapsule.getErrorInfo());
      }
      return callCapsule.getResult();
    } finally {
      try {
        response.close();
      } catch (IOException e) {
        throw new ConduitException("Could not close API response", e);
      }
    }
  }
}
