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

import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.inject.Inject;
import com.googlesource.gerrit.plugins.its.base.its.InvalidTransitionException;
import com.googlesource.gerrit.plugins.its.base.its.ItsFacade;
import com.j2bugzilla.base.BugzillaException;
import com.j2bugzilla.base.ConnectionException;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.Callable;
import org.eclipse.jgit.lib.Config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class BugzillaItsFacade implements ItsFacade {
  private static final String GERRIT_CONFIG_USERNAME = "username";
  private static final String GERRIT_CONFIG_PASSWORD = "password";
  private static final String GERRIT_CONFIG_URL = "url";

  private static final int MAX_ATTEMPTS = 3;

  private Logger log = LoggerFactory.getLogger(BugzillaItsFacade.class);

  private final String pluginName;
  private Config gerritConfig;

  private BugzillaClient client;

  @Inject
  public BugzillaItsFacade(@PluginName String pluginName, @GerritServerConfig Config cfg) {
    this.pluginName = pluginName;
    try {
      this.gerritConfig = cfg;
      log.info(
          "Connected to Bugzilla at "
              + client().getXmlRpcUrl()
              + ", reported version is "
              + client().getServerVersion());
    } catch (Exception ex) {
      log.warn("Bugzilla is currently not available", ex);
    }
  }

  @Override
  public String healthCheck(final Check check) throws IOException {
    return execute(
        new Callable<String>() {
          @Override
          public String call() throws Exception {
            if (check.equals(Check.ACCESS)) return healthCheckAccess();
            else return healthCheckSysinfo();
          }
        });
  }

  @Override
  public void addComment(final String bugId, final String comment) throws IOException {

    execute(
        new Callable<String>() {
          @Override
          public String call() throws Exception {
            log.debug("Adding comment " + comment + " to bug " + bugId);
            client().addComment(bugId, comment);
            log.debug("Added comment " + comment + " to bug " + bugId);
            return bugId;
          }
        });
  }

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

  @Override
  public void performAction(final String bugId, final String actionString) throws IOException {

    execute(
        new Callable<String>() {
          @Override
          public String call() throws Exception {
            String actionName = actionString.substring(0, actionString.indexOf(" "));
            String actionValue = actionString.substring(actionString.indexOf(" ") + 1);
            doPerformAction(bugId, actionName, actionValue);
            return bugId;
          }
        });
  }

  private void doPerformAction(final String bugId, final String fieldName, final String fieldValue)
      throws BugzillaException, IOException, InvalidTransitionException {
    client().performAction(bugId, fieldName.toLowerCase(), fieldValue);
  }

  @Override
  public boolean exists(final String bugId) throws IOException {
    return execute(
        new Callable<Boolean>() {
          @Override
          public Boolean call() throws Exception {
            return client().getBug(bugId) != null;
          }
        });
  }

  public void logout() {
    this.logout(false);
  }

  public void logout(boolean quiet) {
    try {
      client().logout();
    } catch (Exception ex) {
      if (!quiet) log.error("I was unable to logout", ex);
    }
  }

  public Object login() {
    return login(false);
  }

  public Object login(boolean quiet) {
    try {
      String token = client.login(getUsername(), getPassword());
      log.info("Connected to " + getUrl() + " as " + token);
      return token;
    } catch (Exception ex) {
      if (!quiet) {
        log.error("I was unable to login", ex);
      }

      return null;
    }
  }

  private BugzillaClient client() throws IOException {

    if (client == null) {
      try {
        log.debug("Connecting to bugzilla at URL " + getUrl());
        client = new BugzillaClient(getUrl());
        log.debug("Autenthicating as user " + getUsername());
      } catch (Exception ex) {
        log.info("Unable to connect to " + getUrl() + " as " + getUsername());
        throw new IOException(ex);
      }

      login();
    }

    return client;
  }

  private <P> P execute(Callable<P> function) throws IOException {

    int attempt = 0;
    while (true) {
      try {
        return function.call();
      } catch (Exception ex) {
        if (isRecoverable(ex) && ++attempt < MAX_ATTEMPTS) {
          log.debug("Call failed - retrying, attempt {} of {}", attempt, MAX_ATTEMPTS);
          logout(true);
          login(true);
          continue;
        }

        if (ex instanceof IOException) throw ((IOException) ex);
        else throw new IOException(ex);
      }
    }
  }

  private boolean isRecoverable(Exception ex) {
    return false;
  }

  private String getPassword() {
    final String pass = gerritConfig.getString(pluginName, null, GERRIT_CONFIG_PASSWORD);
    return pass;
  }

  private String getUsername() {
    final String user = gerritConfig.getString(pluginName, null, GERRIT_CONFIG_USERNAME);
    return user;
  }

  private String getUrl() {
    final String url = gerritConfig.getString(pluginName, null, GERRIT_CONFIG_URL);
    return url;
  }

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

  private String healthCheckAccess() throws BugzillaException, ConnectionException {
    BugzillaClient client = new BugzillaClient(getUrl());
    client.login(getUsername(), getPassword());
    client.logout();
    final String result = "{\"status\"=\"ok\",\"username\"=\"" + getUsername() + "\"}";
    log.debug("Healtheck on access result: {}", result);
    return result;
  }

  private String healthCheckSysinfo() throws BugzillaException, IOException {
    final String result =
        "{\"status\"=\"ok\",\"system\"=\"Bugzilla\",\"version\"=\""
            + client().getServerVersion()
            + "\",\"url\"=\""
            + getUrl()
            + "\"}";
    log.debug("Healtheck on sysinfo result: {}", result);
    return result;
  }
}
