// 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.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.googlesource.gerrit.plugins.its.phabricator.conduit.results.ConduitPing;
import com.googlesource.gerrit.plugins.its.phabricator.conduit.results.ManiphestEdit;
import com.googlesource.gerrit.plugins.its.phabricator.conduit.results.ManiphestSearch;
import com.googlesource.gerrit.plugins.its.phabricator.conduit.results.ProjectSearch;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Bindings for Phabricator's Conduit API
 *
 * <p>This class is not thread-safe.
 */
public class Conduit {
  public interface Factory {
    Conduit create(@Assisted("baseUrl") String baseUrl, @Assisted("token") String token);
  }

  public static final String ACTION_COMMENT = "comment";

  public static final String ACTION_PROJECT_ADD = "projects.add";

  public static final String ACTION_PROJECT_REMOVE = "projects.remove";

  public static final int CONDUIT_VERSION = 7;

  private final SearchUtils searchUtils;
  private final ConduitConnection conduitConnection;
  private final Gson gson;
  private final String token;

  @Inject
  public Conduit(
      ConduitConnection.Factory conduitConnectionFactory,
      SearchUtils searchUtils,
      @Assisted("baseUrl") String baseUrl,
      @Assisted("token") String token) {
    this.searchUtils = searchUtils;
    this.conduitConnection = conduitConnectionFactory.create(baseUrl);
    this.token = token;
    this.gson = new Gson();
  }

  /** Runs the API's 'conduit.ping' method */
  public ConduitPing conduitPing() throws ConduitException {
    Map<String, Object> params = new HashMap<>();
    JsonElement callResult = conduitConnection.call("conduit.ping", params, token);
    JsonObject callResultWrapper = new JsonObject();
    callResultWrapper.add("hostname", callResult);
    ConduitPing result = gson.fromJson(callResultWrapper, ConduitPing.class);
    return result;
  }

  /** Runs the API's 'maniphest.search' method */
  public ManiphestSearch maniphestSearch(int taskId) throws ConduitException {
    HashMap<String, Object> params = new HashMap<>();
    params.put("constraints", ImmutableMap.of("ids", ImmutableList.of(taskId)));

    JsonElement callResult = conduitConnection.call("maniphest.search", params, token);
    return searchUtils.stream(callResult, ManiphestSearch.class)
        .filter((r) -> r.getId() == taskId)
        .findFirst()
        .orElse(null);
  }

  /** Runs the API's 'maniphest.edit' method */
  public ManiphestEdit maniphestEdit(
      int taskId, String comment, String projectNameToAdd, String projectNameToRemove)
      throws ConduitException {
    ManiphestEdit result = null;
    List<Object> transactions = new ArrayList<>();

    if (!Strings.isNullOrEmpty(comment)) {
      HashMap<String, Object> transaction = new HashMap<>();
      transaction.put("type", ACTION_COMMENT);
      transaction.put("value", comment);

      transactions.add(transaction);
    }

    if (!Strings.isNullOrEmpty(projectNameToAdd)) {
      HashMap<String, Object> transaction = new HashMap<>();
      transaction.put("type", ACTION_PROJECT_ADD);
      transaction.put("value", ImmutableList.of(projectSearch(projectNameToAdd).getPhid()));

      transactions.add(transaction);
    }

    if (!Strings.isNullOrEmpty(projectNameToRemove)) {
      HashMap<String, Object> transaction = new HashMap<>();
      transaction.put("type", ACTION_PROJECT_REMOVE);
      transaction.put("value", ImmutableList.of(projectSearch(projectNameToRemove).getPhid()));

      transactions.add(transaction);
    }

    if (!transactions.isEmpty()) {
      HashMap<String, Object> params = new HashMap<>();
      params.put("objectIdentifier", taskId);
      params.put("transactions", transactions);
      JsonElement callResult = conduitConnection.call("maniphest.edit", params, token);
      result = gson.fromJson(callResult, ManiphestEdit.class);
    }

    return result;
  }

  /** Runs the API's 'project.search' method to match exactly one project name */
  public ProjectSearch projectSearch(String name) throws ConduitException {
    HashMap<String, Object> params = new HashMap<>();
    params.put("constraints", ImmutableMap.of("query", name));

    JsonElement callResult = conduitConnection.call("project.search", params, token);
    return searchUtils.stream(callResult, ProjectSearch.class).findFirst().orElse(null);
  }
}
