// 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;

import com.google.common.collect.Sets;
import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.inject.Inject;
import com.googlesource.gerrit.plugins.its.base.its.ItsFacade;
import com.googlesource.gerrit.plugins.its.phabricator.conduit.Conduit;
import com.googlesource.gerrit.plugins.its.phabricator.conduit.ConduitErrorException;
import com.googlesource.gerrit.plugins.its.phabricator.conduit.ConduitException;
import com.googlesource.gerrit.plugins.its.phabricator.conduit.results.ManiphestSearch;
import com.googlesource.gerrit.plugins.its.phabricator.conduit.results.ManiphestResults;
import com.googlesource.gerrit.plugins.its.phabricator.conduit.results.ProjectSearch;
import java.io.IOException;
import java.net.URL;
import java.util.Set;
import org.eclipse.jgit.lib.Config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class PhabricatorItsFacade implements ItsFacade {
  private static final Logger log = LoggerFactory.getLogger(PhabricatorItsFacade.class);

  private static final String GERRIT_CONFIG_URL = "url";
  private static final String GERRIT_CONFIG_TOKEN = "token";

  private final Conduit conduit;
  private final Gson gson;

  @Inject
  public PhabricatorItsFacade(@PluginName String pluginName, @GerritServerConfig Config cfg) {
    String url = cfg.getString(pluginName, null, GERRIT_CONFIG_URL);
    String token = cfg.getString(pluginName, null, GERRIT_CONFIG_TOKEN);

    this.conduit = new Conduit(url, token);
    this.gson = new Gson();
  }

  @Override
  public void addComment(final String bugId, final String comment) throws IOException {
    int task_id = Integer.parseInt(bugId);
    try {
      conduit.maniphestEdit(task_id, comment);
    } catch (ConduitException e) {
      throw new IOException("Could not update message for task " + task_id, e);
    }
    log.debug("Added comment " + comment + " to bug " + task_id);
  }

  @Override
  public void addRelatedLink(final String issueKey, final URL relatedUrl, String description)
      throws IOException {
    addComment(
        issueKey, "Related URL: " + createLinkForWebui(relatedUrl.toExternalForm(), description));
  }

  @Override
  public boolean exists(final String bugId) throws IOException {
    Boolean ret = false;
    int task_id = Integer.parseInt(bugId);
    try {
      try {
        conduit.maniphestSearch(task_id);
        ret = true;
      } catch (ConduitErrorException e) {
        // An ERR_BAD_TASK just means that the task does not exist.
        // So the default value of ret would be ok
        if (!("ERR_BAD_TASK".equals(e.getErrorCode()))) {
          // So we had an exception that is /not/ ERR_BAD_TASK.
          // We have to relay that to the caller.
          throw e;
        }
      }
    } catch (ConduitException e) {
      throw new IOException("Could not check existence of task " + task_id, e);
    }
    return ret;
  }

  @Override
  public void performAction(final String taskIdString, final String actionString)
      throws IOException {
    int taskId = Integer.parseInt(taskIdString);
    String chopped[] = actionString.split(" ");
    if (chopped.length >= 1) {
      String action = chopped[0];
      switch (action) {
        case "add-project":
          assertParameters(action, chopped, 1);

          maniphestEdit(chopped[1], taskId, Conduit.ACTION_PROJECT_ADD);
          break;
        case "remove-project":
          assertParameters(action, chopped, 1);

          maniphestEdit(chopped[1], taskId, Conduit.ACTION_PROJECT_REMOVE);
          break;
        default:
          throw new IOException("Unknown action " + action);
      }
    } else {
      throw new IOException("Could not parse action " + actionString);
    }
  }

  private void assertParameters(String action, String[] params, int length) throws IOException {
    if (params.length - 1 != length) {
      throw new IOException(
          String.format(
              "Action %s expects exactly %d parameter(s) but %d given",
              action, length, params.length - 1));
    }
  }

  private void maniphestEdit(String projectName, int taskId, String actions) throws IOException {
    try {
      ProjectSearch projectSearch = conduit.projectSearch(projectName);
      String projectPhid = projectSearch.getPhid();

      Set<String> projectPhids = Sets.newHashSet(projectPhid);

      ManiphestResults taskSearch = conduit.maniphestSearch(taskId);
      JsonArray maniphestResultEntryValue = taskSearch.getData().getAsJsonArray();

      for (JsonElement jsonElement : maniphestResultEntryValue) {
        ManiphestSearch maniphestResultManiphestSearch = gson.fromJson(jsonElement, ManiphestSearch.class);
        for (JsonElement jsonElement2 : maniphestResultManiphestSearch.getAttachments().getProjects().getProjectPHIDs().getAsJsonArray()) {
          projectPhids.add(jsonElement2.getAsString());
        }
      }

      conduit.maniphestEdit(taskId, projectPhids, actions);
    } catch (ConduitException e) {
      throw new IOException("Error on conduit", e);
    }
  }

  @Override
  public String healthCheck(final Check check) throws IOException {
    // This method is not used, so there is no need to implement it.
    return "unknown";
  }

  @Override
  public String createLinkForWebui(String url, String text) {
    String ret = "[[" + url;
    if (text != null && !text.isEmpty() && !text.equals(url)) {
      ret += "|" + text;
    }
    ret += "]]";
    return ret;
  }
}
