// 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.index.query.QueryParseException;
import com.google.gerrit.reviewdb.client.Project.NameKey;
import com.google.gerrit.reviewdb.server.ReviewDb;
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.gwtorm.server.OrmException;
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<ReviewDb> schema;
  private final ChangeQueryProcessor qp;
  private final ChangeQueryBuilder changeQuery;

  @Inject
  public PullRequestListController(
      ProjectCache projectsCache,
      GitRepositoryManager repoMgr,
      Provider<ReviewDb> schema,
      GitHubConfig config,
      ChangeQueryProcessor qp,
      ChangeQueryBuilder changeQuery) {
    this.projectsCache = projectsCache;
    this.repoMgr = repoMgr;
    this.schema = schema;
    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(pr.getTitle()));
            prObj.add("body", new JsonPrimitive(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();
    try (ReviewDb db = schema.get()) {
      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, db, allPullRequests, gitRepo, ghRepoName, githubRepo);
          }
        }
      }
      return allPullRequests;
    }
  }

  private int collectPullRequestsFromGitHubRepository(
      int numPullRequests,
      ReviewDb db,
      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(db, 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(
      ReviewDb db, Repository gitRepo, GHPullRequest ghPullRequest)
      throws IncorrectObjectTypeException, IOException {
    boolean pullRequestToImport = false;
    try {
      for (GHPullRequestCommitDetail pullRequestCommit : ghPullRequest.listCommits()) {
        pullRequestToImport |=
            qp.query(changeQuery.commit(pullRequestCommit.getSha())).entities().isEmpty();
      }
      return pullRequestToImport;
    } catch (OrmException | QueryParseException e) {
      LOG.error("Unable to query Gerrit changes for pull-request " + ghPullRequest.getNumber(), e);
      return false;
    }
  }
}
