// Copyright (C) 2016 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.google.gerrit.server;

import static com.google.gerrit.server.notedb.ReviewerStateInternal.REVIEWER;

import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.gerrit.common.data.LabelType;
import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.PatchSetApproval;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.account.AccountDirectory.FillOptions;
import com.google.gerrit.server.account.AccountLoader;
import com.google.gerrit.server.change.ReviewerSuggestion;
import com.google.gerrit.server.change.SuggestReviewers;
import com.google.gerrit.server.change.SuggestedReviewer;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.git.WorkQueue;
import com.google.gerrit.server.index.change.ChangeField;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.project.ProjectControl;
import com.google.gerrit.server.query.Predicate;
import com.google.gerrit.server.query.QueryParseException;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.ChangeQueryBuilder;
import com.google.gerrit.server.query.change.InternalChangeQuery;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;

import org.apache.commons.lang.mutable.MutableDouble;
import org.eclipse.jgit.lib.Config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class ReviewerRecommender {
  private static final Logger log =
      LoggerFactory.getLogger(ReviewersUtil.class);
  private static final double BASE_REVIEWER_WEIGHT = 10;
  private static final double BASE_OWNER_WEIGHT = 1;
  private static final double BASE_COMMENT_WEIGHT = 0.5;
  private static final double[] WEIGHTS = new double[] {
      BASE_REVIEWER_WEIGHT, BASE_OWNER_WEIGHT, BASE_COMMENT_WEIGHT,};
  private static final long PLUGIN_QUERY_TIMEOUT = 500; //ms

  private final ChangeQueryBuilder changeQueryBuilder;
  private final Config config;
  private final DynamicMap<ReviewerSuggestion> reviewerSuggestionPluginMap;
  private final InternalChangeQuery internalChangeQuery;
  private final WorkQueue workQueue;
  private final Provider<ReviewDb> dbProvider;
  private final ApprovalsUtil approvalsUtil;

  @Inject
  ReviewerRecommender(ChangeQueryBuilder changeQueryBuilder,
      DynamicMap<ReviewerSuggestion> reviewerSuggestionPluginMap,
      InternalChangeQuery internalChangeQuery,
      WorkQueue workQueue,
      Provider<ReviewDb> dbProvider,
      ApprovalsUtil approvalsUtil,
      @GerritServerConfig Config config) {
    Set<FillOptions> fillOptions = EnumSet.of(FillOptions.SECONDARY_EMAILS);
    fillOptions.addAll(AccountLoader.DETAILED_OPTIONS);
    this.changeQueryBuilder = changeQueryBuilder;
    this.config = config;
    this.internalChangeQuery = internalChangeQuery;
    this.reviewerSuggestionPluginMap = reviewerSuggestionPluginMap;
    this.workQueue = workQueue;
    this.dbProvider = dbProvider;
    this.approvalsUtil = approvalsUtil;
  }

  public List<Account.Id> suggestReviewers(
      ChangeNotes changeNotes,
      SuggestReviewers suggestReviewers, ProjectControl projectControl,
      List<Account.Id> candidateList)
      throws OrmException {
    String query = suggestReviewers.getQuery();
    double baseWeight = config.getInt("addReviewer", "baseWeight", 1);

    Map<Account.Id, MutableDouble> reviewerScores;
    if (Strings.isNullOrEmpty(query)) {
      reviewerScores = baseRankingForEmptyQuery(baseWeight);
    } else {
      reviewerScores = baseRankingForCandidateList(
          candidateList, projectControl, baseWeight);
    }

    // Send the query along with a candidate list to all plugins and merge the
    // results. Plugins don't necessarily need to use the candidates list, they
    // can also return non-candidate account ids.
    List<Callable<Set<SuggestedReviewer>>> tasks =
        new ArrayList<>(reviewerSuggestionPluginMap.plugins().size());
    List<Double> weights =
        new ArrayList<>(reviewerSuggestionPluginMap.plugins().size());

    for (DynamicMap.Entry<ReviewerSuggestion> plugin :
        reviewerSuggestionPluginMap) {
      tasks.add(() -> plugin.getProvider().get()
          .suggestReviewers(projectControl.getProject().getNameKey(),
              changeNotes.getChangeId(), query, reviewerScores.keySet()));
      String pluginWeight = config.getString("addReviewer",
          plugin.getPluginName() + "-" + plugin.getExportName(), "weight");
      if (Strings.isNullOrEmpty(pluginWeight)) {
        pluginWeight = "1";
      }
      try {
        weights.add(Double.parseDouble(pluginWeight));
      } catch (NumberFormatException e) {
        log.error("Exception while parsing weight for " +
            plugin.getPluginName() + "-" + plugin.getExportName(), e);
        weights.add(1d);
      }
    }

    try {
      List<Future<Set<SuggestedReviewer>>> futures = workQueue
          .getDefaultQueue()
          .invokeAll(tasks, PLUGIN_QUERY_TIMEOUT, TimeUnit.MILLISECONDS);
      Iterator<Double> weightIterator = weights.iterator();
      for (Future<Set<SuggestedReviewer>> f : futures) {
        double weight = weightIterator.next();
        for (SuggestedReviewer s : f.get()) {
          if (reviewerScores.containsKey(s.account)) {
            reviewerScores.get(s.account).add(s.score * weight);
          } else {
            reviewerScores.put(s.account, new MutableDouble(s.score * weight));
          }
        }
      }
    } catch (ExecutionException | InterruptedException e) {
      log.error("Exception while suggesting reviewers", e);
      return ImmutableList.of();
    }

    if (changeNotes != null) {
      // Remove change owner
      reviewerScores.remove(changeNotes.getChange().getOwner());

      // Remove existing reviewers
      reviewerScores.keySet().removeAll(
          approvalsUtil.getReviewers(dbProvider.get(), changeNotes)
              .byState(REVIEWER));
    }

    // Sort results
    Stream<Entry<Account.Id, MutableDouble>> sorted =
        reviewerScores.entrySet().stream()
            .sorted(Collections.reverseOrder(Map.Entry.comparingByValue()));
    List<Account.Id> sortedSuggestions = sorted
        .map(Map.Entry::getKey)
        .collect(Collectors.toList());
    return sortedSuggestions;
  }

  private Map<Account.Id, MutableDouble> baseRankingForEmptyQuery(
      double baseWeight) throws OrmException{
    // Get the user's last 25 changes, check approvals
    try {
      List<ChangeData> result = internalChangeQuery
          .setLimit(25)
          .setRequestedFields(ImmutableSet.of(ChangeField.REVIEWER.getName()))
          .query(changeQueryBuilder.owner("self"));
      Map<Account.Id, MutableDouble> suggestions = new HashMap<>();
      for (ChangeData cd : result) {
        for (PatchSetApproval approval : cd.currentApprovals()) {
          Account.Id id = approval.getAccountId();
          if (suggestions.containsKey(id)) {
            suggestions.get(id).add(baseWeight);
          } else {
            suggestions.put(id, new MutableDouble(baseWeight));
          }
        }
      }
      return suggestions;
    } catch (QueryParseException e) {
      // Unhandled, because owner:self will never provoke a QueryParseException
      log.error("Exception while suggesting reviewers", e);
      return ImmutableMap.of();
    }
  }

  private Map<Account.Id, MutableDouble> baseRankingForCandidateList(
      List<Account.Id> candidates,
      ProjectControl projectControl,
      double baseWeight) throws OrmException {
    // Get each reviewer's activity based on number of applied labels
    // (weighted 10d), number of comments (weighted 0.5d) and number of owned
    // changes (weighted 1d).
    Map<Account.Id, MutableDouble> reviewers = new LinkedHashMap<>();
    if (candidates.size() == 0) {
      return reviewers;
    }
    List<Predicate<ChangeData>> predicates = new ArrayList<>();
    for (Account.Id id : candidates) {
      try {
        Predicate<ChangeData> projectQuery =
            changeQueryBuilder.project(projectControl.getProject().getName());

        // Get all labels for this project and create a compound OR query to
        // fetch all changes where users have applied one of these labels
        List<LabelType> labelTypes =
            projectControl.getLabelTypes().getLabelTypes();
        List<Predicate<ChangeData>> labelPredicates =
            new ArrayList<>(labelTypes.size());
        for (LabelType type : labelTypes) {
          labelPredicates
              .add(changeQueryBuilder.label(type.getName() + ",user=" + id));
        }
        Predicate<ChangeData> reviewerQuery =
            Predicate.and(projectQuery, Predicate.or(labelPredicates));

        Predicate<ChangeData> ownerQuery = Predicate.and(projectQuery,
            changeQueryBuilder.owner(id.toString()));
        Predicate<ChangeData> commentedByQuery = Predicate.and(projectQuery,
            changeQueryBuilder.commentby(id.toString()));

        predicates.add(reviewerQuery);
        predicates.add(ownerQuery);
        predicates.add(commentedByQuery);
        reviewers.put(id, new MutableDouble());
      } catch (QueryParseException e) {
        // Unhandled: If an exception is thrown, we won't increase the
        // candidates's score
        log.error("Exception while suggesting reviewers", e);
      }
    }

    List<List<ChangeData>> result = internalChangeQuery
        .setLimit(25)
        .setRequestedFields(ImmutableSet.of())
        .query(predicates);

    Iterator<List<ChangeData>> queryResultIterator = result.iterator();
    Iterator<Account.Id> reviewersIterator = reviewers.keySet().iterator();

    int i = 0;
    Account.Id currentId = null;
    while (queryResultIterator.hasNext()) {
      List<ChangeData> currentResult = queryResultIterator.next();
      if (i % WEIGHTS.length == 0) {
        currentId = reviewersIterator.next();
      }

      reviewers.get(currentId).add(WEIGHTS[i % WEIGHTS.length] *
          baseWeight * currentResult.size());
      i++;
    }
    return reviewers;
  }
}
