// Copyright (C) 2017 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.automerger;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;
import com.google.gerrit.common.data.ParameterizedString;
import com.google.gerrit.extensions.api.GerritApi;
import com.google.gerrit.extensions.client.ListChangesOption;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.common.CommitInfo;
import com.google.gerrit.extensions.common.RevisionInfo;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.reviewdb.client.BranchNameKey;
import com.google.gerrit.reviewdb.client.PatchSet.Id;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.git.CodeReviewCommit;
import com.google.gerrit.server.git.validators.MergeValidationException;
import com.google.gerrit.server.git.validators.MergeValidationListener;
import com.google.gerrit.server.project.ProjectState;
import com.google.inject.Inject;
import java.io.IOException;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Repository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * MergeValidator will validate that all downstream changes are uploaded for review before
 * submission.
 */
public class MergeValidator implements MergeValidationListener {
  private static final Logger log = LoggerFactory.getLogger(MergeValidator.class);

  protected GerritApi gApi;
  protected ConfigLoader config;

  @Inject
  public MergeValidator(GerritApi gApi, ConfigLoader config) {
    this.gApi = gApi;
    this.config = config;
  }

  @Override
  public void onPreMerge(
      Repository repo,
      CodeReviewCommit commit,
      ProjectState destProject,
      BranchNameKey destBranch,
      Id patchSetId,
      IdentifiedUser caller)
      throws MergeValidationException {
    int changeId = commit.change().getChangeId();
    try {
      ChangeInfo upstreamChange =
          gApi.changes().id(changeId).get(EnumSet.of(ListChangesOption.CURRENT_REVISION));
      Set<String> missingDownstreams = getMissingDownstreamMerges(upstreamChange);
      if (!missingDownstreams.isEmpty()) {
        throw new MergeValidationException(getMissingDownstreamsMessage(missingDownstreams));
      }
    } catch (RestApiException
        | IOException
        | ConfigInvalidException
        | InvalidQueryParameterException e) {
      log.error("Automerger plugin failed onPreMerge for {}", changeId, e);
      e.printStackTrace();
      throw new MergeValidationException("Error when validating merge for: " + changeId);
    }
  }

  private String getMissingDownstreamsMessage(Set<String> missingDownstreams)
      throws ConfigInvalidException {
    String missingDownstreamsMessage = config.getMissingDownstreamsMessage();
    ParameterizedString pattern = new ParameterizedString(missingDownstreamsMessage);
    return pattern.replace(getSubstitutionMap(missingDownstreams));
  }

  private Map<String, String> getSubstitutionMap(Set<String> missingDownstreams) {
    Map<String, String> substitutionMap = new HashMap<>();
    substitutionMap.put("missingDownstreams", Joiner.on(", ").join(missingDownstreams));
    return substitutionMap;
  }

  @VisibleForTesting
  protected Set<String> getMissingDownstreamMerges(ChangeInfo upstreamChange)
      throws RestApiException, IOException, ConfigInvalidException, InvalidQueryParameterException {
    Set<String> missingDownstreamBranches = new HashSet<>();

    Set<String> downstreamBranches =
        config.getDownstreamBranches(upstreamChange.branch, upstreamChange.project);
    for (String downstreamBranch : downstreamBranches) {
      boolean dsExists = false;
      QueryBuilder queryBuilder = new QueryBuilder();
      if (upstreamChange.topic == null || upstreamChange.topic.equals("")) {
        // If topic is null or empty, we immediately know that downstream is missing.
        missingDownstreamBranches.add(downstreamBranch);
        continue;
      }
      queryBuilder.addParameter("topic", upstreamChange.topic);
      queryBuilder.addParameter("branch", downstreamBranch);
      queryBuilder.addParameter("status", "open");
      List<ChangeInfo> changes =
          gApi.changes()
              .query(queryBuilder.get())
              .withOptions(ListChangesOption.ALL_REVISIONS, ListChangesOption.CURRENT_COMMIT)
              .get();
      for (ChangeInfo change : changes) {
        RevisionInfo revision = change.revisions.get(change.currentRevision);
        List<CommitInfo> parents = revision.commit.parents;
        if (parents.size() > 1) {
          String secondParent = parents.get(1).commit;
          if (secondParent.equals(upstreamChange.currentRevision)) {
            dsExists = true;
            break;
          }
        }
      }
      if (!dsExists) {
        missingDownstreamBranches.add(downstreamBranch);
      }
    }
    return missingDownstreamBranches;
  }
}
