// 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.hooks.bz;

import java.io.IOException;
import java.net.URL;
import java.util.Map;
import java.util.concurrent.Callable;

import org.eclipse.jgit.lib.Config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.gerrit.server.config.GerritServerConfig;
import com.google.inject.Inject;
import com.googlesource.gerrit.plugins.hooks.its.InvalidTransitionException;
import com.googlesource.gerrit.plugins.hooks.its.ItsFacade;
import com.j2bugzilla.base.Bug;
import com.j2bugzilla.base.BugzillaException;
import com.j2bugzilla.base.ConnectionException;
import com.j2bugzilla.rpc.GetLegalValues.Fields;

public class BugzillaItsFacade implements ItsFacade {
  public static final String ITS_NAME_BUGZILLA = "bugzilla";

  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 Config gerritConfig;

  private BugzillaClient client;

  @Inject
  public BugzillaItsFacade(@GerritServerConfig Config cfg) {
    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 name() {
    return "Bugzilla";
  }

  @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(" ") - 1);
        String actionValue = actionString.substring(actionString.indexOf(" "));
        doPerformAction(bugId, actionName, actionValue);
        return bugId;
      }});
  }

  private void doPerformAction(final String bugId, final String fieldName, final String fieldValue)
      throws BugzillaException, IOException {
    String actionKey = null;
    Map<String, Fields> fields = client().getFields();
    for (Map.Entry<String, Fields> field : fields.entrySet()) {
      if (field.getKey().equalsIgnoreCase(fieldName)) {
        actionKey = field.getKey();
      }
    }

    if (actionKey != null) {
      log.debug("Executing action " + actionKey + " on issue " + bugId);
      client().performAction(bugId, actionKey, fieldValue);
    } else {
      StringBuilder sb = new StringBuilder();
      for (Map.Entry<String, Fields> action : fields.entrySet()) {
        if (sb.length() > 0) sb.append(',');
        sb.append('\'');
        sb.append(action.getKey());
        sb.append('\'');
      }

      log.error("Action " + fieldName
          + " not found within available actions: " + sb);
      throw new InvalidTransitionException("Action " + fieldName
          + " not executable on issue " + bugId);
    }
  }

  @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 logout", ex);
      }

      return null;
    }
  }

  private BugzillaClient client() throws IOException {

    if (client == null) {
      try {
        log.debug("Connecting to bugzillab at URL " + getUrl());
        client = new BugzillaClient(getUrl());
        log.debug("Autenthicating as user " + getUsername());
      } catch (Exception ex) {
        log.info("Unable to connect to Connected 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(ITS_NAME_BUGZILLA, null,
            GERRIT_CONFIG_PASSWORD);
    return pass;
  }

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

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

  @Override
  public String createLinkForWebui(String url, String text) {
    return "["+text+"|"+url+"]";
  }

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