// Copyright (C) 2019 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.criteo.gerrit.plugins.automerge;

import static com.google.gerrit.server.permissions.ChangePermission.READ;

import com.google.gerrit.common.data.SubmitRecord;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.extensions.api.changes.RelatedChangeAndCommitInfo;
import com.google.gerrit.extensions.api.changes.RelatedChangesInfo;
import com.google.gerrit.extensions.api.changes.SubmitInput;
import com.google.gerrit.extensions.client.ChangeStatus;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.Emails;
import com.google.gerrit.server.change.ChangeResource;
import com.google.gerrit.server.change.RevisionResource;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gerrit.server.project.NoSuchProjectException;
import com.google.gerrit.server.project.SubmitRuleEvaluator;
import com.google.gerrit.server.project.SubmitRuleOptions;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.restapi.change.GetRelated;
import com.google.gerrit.server.restapi.change.PostReview;
import com.google.gerrit.server.restapi.change.Submit;
import com.google.inject.Inject;
import java.io.IOException;
import java.util.List;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class AtomicityHelper {

  private static final Logger log = LoggerFactory.getLogger(AtomicityHelper.class);

  @Inject ChangeData.Factory changeDataFactory;

  @Inject AutomergeConfig config;

  @Inject private IdentifiedUser.GenericFactory factory;

  @Inject GetRelated getRelated;

  @Inject Submit submitter;

  @Inject Emails emails;

  @Inject ChangeNotes.Factory changeNotesFactory;

  @Inject PermissionBackend permissionBackend;

  @Inject SubmitRuleEvaluator.Factory submitRuleEvaluatorFactory;

  @Inject ChangeResource.Factory changeResourceFactory;

  /**
   * Check if the current patchset of the specified change has dependent unmerged changes.
   *
   * @param project
   * @param number
   * @return true or false
   * @throws IOException
   * @throws NoSuchChangeException
   * @throws NoSuchProjectException
   * @throws PermissionBackendException
   */
  public boolean hasDependentReview(String project, int number)
      throws IOException, NoSuchChangeException, NoSuchProjectException,
          PermissionBackendException {
    RevisionResource r = getRevisionResource(project, number);
    RelatedChangesInfo related = getRelated.apply(r);
    log.debug(String.format("Checking for related changes on review %d", number));

    String checkedCommitSha1 = r.getPatchSet().getRevision().get();
    int firstParentIndex = 0;
    int i = 0;
    for (RelatedChangeAndCommitInfo c : related.changes) {
      if (checkedCommitSha1.equals(c.commit.commit)) {
        firstParentIndex = i + 1;
        log.debug(
            String.format(
                "First parent index on review %d is %d on commit %s",
                number, firstParentIndex, c.commit.commit));
        break;
      }
      i++;
    }

    boolean hasNonMergedParent = false;
    for (RelatedChangeAndCommitInfo c :
        related.changes.subList(firstParentIndex, related.changes.size())) {
      if (!ChangeStatus.MERGED.toString().equals(c.status)) {
        log.info(
            String.format(
                "Found non merged parent commit on review %d: %s", number, c.commit.commit));
        hasNonMergedParent = true;
        break;
      }
    }

    return hasNonMergedParent;
  }

  /**
   * Check if a change is an atomic change or not. A change is atomic if it has the atomic topic
   * prefix.
   *
   * @param change a Change instance
   * @return true or false
   */
  public boolean isAtomicReview(final Change change) {
    final boolean atomic = change.topic != null && change.topic.startsWith(config.getTopicPrefix());
    log.debug(
        String.format("Checking if change %s is an atomic change: %b", change.number, atomic));
    return atomic;
  }

  /**
   * Check if a change is submitable.
   *
   * @param project a change project
   * @param change a change number
   * @return true or false
   */
  public boolean isSubmittable(String project, int change) {
    ChangeData changeData =
        changeDataFactory.create(
            new Project.NameKey(project), new com.google.gerrit.reviewdb.client.Change.Id(change));
    // For draft reviews, the patchSet must be set to avoid an NPE.
    final List<SubmitRecord> cansubmit =
        submitRuleEvaluatorFactory.create(SubmitRuleOptions.defaults()).evaluate(changeData);
    log.debug(String.format("Checking if change %d is submitable.", change));
    for (SubmitRecord submit : cansubmit) {
      if (submit.status != SubmitRecord.Status.OK) {
        log.debug(String.format("Change %d is not submitable", change));
        return false;
      }
    }
    log.debug(String.format("Change %d is submitable", change));
    return true;
  }

  /** Merge a review. */
  public void mergeReview(String project, int number) throws Exception {
    submitter.apply(getRevisionResource(project, number), new SubmitInput());
  }

  public RevisionResource getRevisionResource(String project, int changeNumber) {
    com.google.gerrit.reviewdb.client.Change.Id changeId =
        new com.google.gerrit.reviewdb.client.Change.Id(changeNumber);
    ChangeNotes notes = changeNotesFactory.createChecked(changeId);
    try {
      permissionBackend.user(getBotUser()).change(notes).check(READ);
      ChangeData changeData = changeDataFactory.create(new Project.NameKey(project), changeId);

      RevisionResource r =
          new RevisionResource(
              changeResourceFactory.create(changeData.notes(), getBotUser()),
              changeData.currentPatchSet());
      return r;
    } catch (AuthException | PermissionBackendException e) {
      throw new NoSuchChangeException(changeId);
    }
  }

  private IdentifiedUser getBotUser() {
    try {
      Set<Account.Id> ids = emails.getAccountFor(config.getBotEmail());
      if (ids.isEmpty()) {
        throw new RuntimeException("No user found with email: " + config.getBotEmail());
      }
      return factory.create(ids.iterator().next());
    } catch (IOException | StorageException e) {
      throw new RuntimeException("Unable to get account with email: " + config.getBotEmail(), e);
    }
  }
}
