// 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.github.wizard;

import com.google.common.base.Optional;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.gerrit.entities.Project.NameKey;
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.query.change.ChangeQueryBuilder;
import com.google.gerrit.server.query.change.ChangeQueryProcessor;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import com.googlesource.gerrit.plugins.github.GitHubConfig;
import com.googlesource.gerrit.plugins.github.oauth.GitHubLogin;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.lib.Repository;
import org.kohsuke.github.GHIssueState;
import org.kohsuke.github.GHPullRequest;
import org.kohsuke.github.GHPullRequestCommitDetail;
import org.kohsuke.github.GHRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Singleton
public class PullRequestListController implements VelocityController {
  private static final Logger LOG = LoggerFactory.getLogger(PullRequestListController.class);
  private static final String DATE_FMT = "yyyy-MM-dd HH:mm z";

  private final GitHubConfig config;
  private final ProjectCache projectsCache;
  private final GitRepositoryManager repoMgr;
  private final Provider<ChangeQueryProcessor> qp;
  private final ChangeQueryBuilder changeQuery;

  @Inject
  public PullRequestListController(
      ProjectCache projectsCache,
      GitRepositoryManager repoMgr,
      GitHubConfig config,
      Provider<ChangeQueryProcessor> qp,
      ChangeQueryBuilder changeQuery) {
    this.projectsCache = projectsCache;
    this.repoMgr = repoMgr;
    this.config = config;
    this.qp = qp;
    this.changeQuery = changeQuery;
  }

  @Override
  public void doAction(
      IdentifiedUser user,
      GitHubLogin hubLogin,
      HttpServletRequest req,
      HttpServletResponse resp,
      ControllerErrors errors)
      throws ServletException, IOException {
    try (PrintWriter out = resp.getWriter()) {
      SimpleDateFormat dateFmt = new SimpleDateFormat(DATE_FMT);
      String organisation = req.getParameter("organisation");
      String repository = req.getParameter("repository");
      Map<String, List<GHPullRequest>> pullRequests =
          getPullRequests(hubLogin, organisation, repository);

      JsonArray reposPullRequests = new JsonArray();
      for (Entry<String, List<GHPullRequest>> repoEntry : pullRequests.entrySet()) {
        JsonObject repoPullRequests = new JsonObject();

        repoPullRequests.add("repository", new JsonPrimitive(repoEntry.getKey()));

        if (repoEntry.getValue() != null) {
          JsonArray prArray = new JsonArray();
          for (GHPullRequest pr : repoEntry.getValue()) {
            JsonObject prObj = new JsonObject();
            prObj.add("id", new JsonPrimitive(new Integer(pr.getNumber())));
            prObj.add("title", new JsonPrimitive(Strings.nullToEmpty(pr.getTitle())));
            prObj.add("body", new JsonPrimitive(Strings.nullToEmpty(pr.getBody())));
            prObj.add(
                "author", new JsonPrimitive(pr.getUser() == null ? "" : pr.getUser().getLogin()));
            prObj.add("status", new JsonPrimitive(pr.getState().name()));
            prObj.add("date", new JsonPrimitive(dateFmt.format(pr.getUpdatedAt())));

            prArray.add(prObj);
          }
          repoPullRequests.add("pullrequests", prArray);
        }

        reposPullRequests.add(repoPullRequests);
      }
      out.println(reposPullRequests.toString());
    }
  }

  private Map<String, List<GHPullRequest>> getPullRequests(
      GitHubLogin hubLogin, String organisation, String repository) throws IOException {
    return getPullRequests(
        hubLogin, projectsCache.byName(organisation + "/" + Strings.nullToEmpty(repository)));
  }

  private Map<String, List<GHPullRequest>> getPullRequests(
      GitHubLogin login, Iterable<NameKey> repos) throws IOException {
    int numPullRequests = 0;
    Map<String, List<GHPullRequest>> allPullRequests = Maps.newHashMap();
    for (NameKey gerritRepoName : repos) {
      try (Repository gitRepo = repoMgr.openRepository(gerritRepoName)) {
        String ghRepoName = gerritRepoName.get().split("/")[1];
        Optional<GHRepository> githubRepo = getGHRepository(login, gerritRepoName);
        if (githubRepo.isPresent()) {
          numPullRequests =
              collectPullRequestsFromGitHubRepository(
                  numPullRequests, allPullRequests, gitRepo, ghRepoName, githubRepo);
        }
      }
    }
    return allPullRequests;
  }

  private int collectPullRequestsFromGitHubRepository(
      int numPullRequests,
      Map<String, List<GHPullRequest>> allPullRequests,
      Repository gitRepo,
      String ghRepoName,
      Optional<GHRepository> githubRepo)
      throws IncorrectObjectTypeException, IOException {
    List<GHPullRequest> repoPullRequests = Lists.newArrayList();

    int count = numPullRequests;
    if (count < config.pullRequestListLimit) {
      for (GHPullRequest ghPullRequest : githubRepo.get().listPullRequests(GHIssueState.OPEN)) {

        if (isAnyCommitOfPullRequestToBeImported(gitRepo, ghPullRequest)) {
          repoPullRequests.add(ghPullRequest);
          count++;
        }
      }
      if (repoPullRequests.size() > 0) {
        allPullRequests.put(ghRepoName, repoPullRequests);
      }
    } else {
      allPullRequests.put(ghRepoName, null);
    }
    return count;
  }

  private Optional<GHRepository> getGHRepository(GitHubLogin login, NameKey gerritRepoName)
      throws IOException {
    try {
      return Optional.of(login.getHub().getRepository(gerritRepoName.get()));
    } catch (FileNotFoundException e) {
      LOG.debug("GitHub repository {} cannot be found", gerritRepoName.get());
      return Optional.absent();
    }
  }

  private boolean isAnyCommitOfPullRequestToBeImported(
      Repository gitRepo, GHPullRequest ghPullRequest)
      throws IncorrectObjectTypeException, IOException {
    boolean pullRequestToImport = false;
    try {
      for (GHPullRequestCommitDetail pullRequestCommit : ghPullRequest.listCommits()) {
        pullRequestToImport |=
            qp.get().query(changeQuery.commit(pullRequestCommit.getSha())).entities().isEmpty();
      }
      return pullRequestToImport;
    } catch (QueryParseException e) {
      LOG.error("Unable to query Gerrit changes for pull-request " + ghPullRequest.getNumber(), e);
      return false;
    }
  }
}
