// Copyright (C) 2015 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 java.nio.charset.StandardCharsets.UTF_8;
import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toSet;

import com.google.auto.value.AutoValue;
import com.google.common.base.CharMatcher;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Sets;
import com.google.common.flogger.FluentLogger;
import com.google.common.primitives.Ints;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.change.ChangeResource;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.index.change.ChangeField;
import com.google.gerrit.server.index.change.ChangeIndexer;
import com.google.gerrit.server.logging.TraceContext;
import com.google.gerrit.server.logging.TraceContext.TraceTimer;
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gerrit.server.query.change.ChangeData;
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 com.google.inject.Singleton;
import java.io.IOException;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import org.eclipse.jgit.lib.BatchRefUpdate;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.NullProgressMonitor;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefDatabase;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.ReceiveCommand;

@Singleton
public class StarredChangesUtil {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  @AutoValue
  public abstract static class StarField {
    private static final String SEPARATOR = ":";

    public static StarField parse(String s) {
      int p = s.indexOf(SEPARATOR);
      if (p >= 0) {
        Integer id = Ints.tryParse(s.substring(0, p));
        if (id == null) {
          return null;
        }
        Account.Id accountId = new Account.Id(id);
        String label = s.substring(p + 1);
        return create(accountId, label);
      }
      return null;
    }

    public static StarField create(Account.Id accountId, String label) {
      return new AutoValue_StarredChangesUtil_StarField(accountId, label);
    }

    public abstract Account.Id accountId();

    public abstract String label();

    @Override
    public String toString() {
      return accountId() + SEPARATOR + label();
    }
  }

  @AutoValue
  public abstract static class StarRef {
    private static final StarRef MISSING =
        new AutoValue_StarredChangesUtil_StarRef(null, ImmutableSortedSet.of());

    private static StarRef create(Ref ref, Iterable<String> labels) {
      return new AutoValue_StarredChangesUtil_StarRef(
          requireNonNull(ref), ImmutableSortedSet.copyOf(labels));
    }

    @Nullable
    public abstract Ref ref();

    public abstract ImmutableSortedSet<String> labels();

    public ObjectId objectId() {
      return ref() != null ? ref().getObjectId() : ObjectId.zeroId();
    }
  }

  public static class IllegalLabelException extends Exception {
    private static final long serialVersionUID = 1L;

    IllegalLabelException(String message) {
      super(message);
    }
  }

  public static class InvalidLabelsException extends IllegalLabelException {
    private static final long serialVersionUID = 1L;

    InvalidLabelsException(Set<String> invalidLabels) {
      super(String.format("invalid labels: %s", Joiner.on(", ").join(invalidLabels)));
    }
  }

  public static class MutuallyExclusiveLabelsException extends IllegalLabelException {
    private static final long serialVersionUID = 1L;

    MutuallyExclusiveLabelsException(String label1, String label2) {
      super(
          String.format(
              "The labels %s and %s are mutually exclusive. Only one of them can be set.",
              label1, label2));
    }
  }

  public static final String DEFAULT_LABEL = "star";
  public static final String IGNORE_LABEL = "ignore";
  public static final String REVIEWED_LABEL = "reviewed";
  public static final String UNREVIEWED_LABEL = "unreviewed";
  public static final ImmutableSortedSet<String> DEFAULT_LABELS =
      ImmutableSortedSet.of(DEFAULT_LABEL);

  private final GitRepositoryManager repoManager;
  private final GitReferenceUpdated gitRefUpdated;
  private final AllUsersName allUsers;
  private final Provider<ReviewDb> dbProvider;
  private final Provider<PersonIdent> serverIdent;
  private final ChangeIndexer indexer;
  private final Provider<InternalChangeQuery> queryProvider;

  @Inject
  StarredChangesUtil(
      GitRepositoryManager repoManager,
      GitReferenceUpdated gitRefUpdated,
      AllUsersName allUsers,
      Provider<ReviewDb> dbProvider,
      @GerritPersonIdent Provider<PersonIdent> serverIdent,
      ChangeIndexer indexer,
      Provider<InternalChangeQuery> queryProvider) {
    this.repoManager = repoManager;
    this.gitRefUpdated = gitRefUpdated;
    this.allUsers = allUsers;
    this.dbProvider = dbProvider;
    this.serverIdent = serverIdent;
    this.indexer = indexer;
    this.queryProvider = queryProvider;
  }

  public ImmutableSortedSet<String> getLabels(Account.Id accountId, Change.Id changeId)
      throws OrmException {
    try (Repository repo = repoManager.openRepository(allUsers)) {
      return readLabels(repo, RefNames.refsStarredChanges(changeId, accountId)).labels();
    } catch (IOException e) {
      throw new OrmException(
          String.format(
              "Reading stars from change %d for account %d failed",
              changeId.get(), accountId.get()),
          e);
    }
  }

  public ImmutableSortedSet<String> star(
      Account.Id accountId,
      Project.NameKey project,
      Change.Id changeId,
      Set<String> labelsToAdd,
      Set<String> labelsToRemove)
      throws OrmException, IllegalLabelException {
    try (Repository repo = repoManager.openRepository(allUsers)) {
      String refName = RefNames.refsStarredChanges(changeId, accountId);
      StarRef old = readLabels(repo, refName);

      Set<String> labels = new HashSet<>(old.labels());
      if (labelsToAdd != null) {
        labels.addAll(labelsToAdd);
      }
      if (labelsToRemove != null) {
        labels.removeAll(labelsToRemove);
      }

      if (labels.isEmpty()) {
        deleteRef(repo, refName, old.objectId());
      } else {
        checkMutuallyExclusiveLabels(labels);
        updateLabels(repo, refName, old.objectId(), labels);
      }

      indexer.index(dbProvider.get(), project, changeId);
      return ImmutableSortedSet.copyOf(labels);
    } catch (IOException e) {
      throw new OrmException(
          String.format("Star change %d for account %d failed", changeId.get(), accountId.get()),
          e);
    }
  }

  public void unstarAll(Project.NameKey project, Change.Id changeId) throws OrmException {
    try (Repository repo = repoManager.openRepository(allUsers);
        RevWalk rw = new RevWalk(repo)) {
      BatchRefUpdate batchUpdate = repo.getRefDatabase().newBatchUpdate();
      batchUpdate.setAllowNonFastForwards(true);
      batchUpdate.setRefLogIdent(serverIdent.get());
      batchUpdate.setRefLogMessage("Unstar change " + changeId.get(), true);
      for (Account.Id accountId : byChangeFromIndex(changeId).keySet()) {
        String refName = RefNames.refsStarredChanges(changeId, accountId);
        Ref ref = repo.getRefDatabase().getRef(refName);
        batchUpdate.addCommand(new ReceiveCommand(ref.getObjectId(), ObjectId.zeroId(), refName));
      }
      batchUpdate.execute(rw, NullProgressMonitor.INSTANCE);
      for (ReceiveCommand command : batchUpdate.getCommands()) {
        if (command.getResult() != ReceiveCommand.Result.OK) {
          throw new IOException(
              String.format(
                  "Unstar change %d failed, ref %s could not be deleted: %s",
                  changeId.get(), command.getRefName(), command.getResult()));
        }
      }
      indexer.index(dbProvider.get(), project, changeId);
    } catch (IOException e) {
      throw new OrmException(String.format("Unstar change %d failed", changeId.get()), e);
    }
  }

  public ImmutableMap<Account.Id, StarRef> byChange(Change.Id changeId) throws OrmException {
    try (Repository repo = repoManager.openRepository(allUsers)) {
      ImmutableMap.Builder<Account.Id, StarRef> builder = ImmutableMap.builder();
      for (String refPart : getRefNames(repo, RefNames.refsStarredChangesPrefix(changeId))) {
        Integer id = Ints.tryParse(refPart);
        if (id == null) {
          continue;
        }
        Account.Id accountId = new Account.Id(id);
        builder.put(accountId, readLabels(repo, RefNames.refsStarredChanges(changeId, accountId)));
      }
      return builder.build();
    } catch (IOException e) {
      throw new OrmException(
          String.format("Get accounts that starred change %d failed", changeId.get()), e);
    }
  }

  public ImmutableListMultimap<Account.Id, String> byChangeFromIndex(Change.Id changeId)
      throws OrmException {
    List<ChangeData> changeData =
        queryProvider
            .get()
            .setRequestedFields(ChangeField.ID, ChangeField.STAR)
            .byLegacyChangeId(changeId);
    if (changeData.size() != 1) {
      throw new NoSuchChangeException(changeId);
    }
    return changeData.get(0).stars();
  }

  private static Set<String> getRefNames(Repository repo, String prefix) throws IOException {
    RefDatabase refDb = repo.getRefDatabase();
    return refDb
        .getRefsByPrefix(prefix)
        .stream()
        .map(r -> r.getName().substring(prefix.length()))
        .collect(toSet());
  }

  public ObjectId getObjectId(Account.Id accountId, Change.Id changeId) {
    try (Repository repo = repoManager.openRepository(allUsers)) {
      Ref ref = repo.exactRef(RefNames.refsStarredChanges(changeId, accountId));
      return ref != null ? ref.getObjectId() : ObjectId.zeroId();
    } catch (IOException e) {
      logger.atSevere().withCause(e).log(
          "Getting star object ID for account %d on change %d failed",
          accountId.get(), changeId.get());
      return ObjectId.zeroId();
    }
  }

  public void ignore(ChangeResource rsrc) throws OrmException, IllegalLabelException {
    star(
        rsrc.getUser().asIdentifiedUser().getAccountId(),
        rsrc.getProject(),
        rsrc.getChange().getId(),
        ImmutableSet.of(IGNORE_LABEL),
        ImmutableSet.of());
  }

  public void unignore(ChangeResource rsrc) throws OrmException, IllegalLabelException {
    star(
        rsrc.getUser().asIdentifiedUser().getAccountId(),
        rsrc.getProject(),
        rsrc.getChange().getId(),
        ImmutableSet.of(),
        ImmutableSet.of(IGNORE_LABEL));
  }

  public boolean isIgnoredBy(Change.Id changeId, Account.Id accountId) throws OrmException {
    return getLabels(accountId, changeId).contains(IGNORE_LABEL);
  }

  public boolean isIgnored(ChangeResource rsrc) throws OrmException {
    return isIgnoredBy(rsrc.getChange().getId(), rsrc.getUser().asIdentifiedUser().getAccountId());
  }

  private static String getReviewedLabel(Change change) {
    return getReviewedLabel(change.currentPatchSetId().get());
  }

  private static String getReviewedLabel(int ps) {
    return REVIEWED_LABEL + "/" + ps;
  }

  private static String getUnreviewedLabel(Change change) {
    return getUnreviewedLabel(change.currentPatchSetId().get());
  }

  private static String getUnreviewedLabel(int ps) {
    return UNREVIEWED_LABEL + "/" + ps;
  }

  public void markAsReviewed(ChangeResource rsrc) throws OrmException, IllegalLabelException {
    star(
        rsrc.getUser().asIdentifiedUser().getAccountId(),
        rsrc.getProject(),
        rsrc.getChange().getId(),
        ImmutableSet.of(getReviewedLabel(rsrc.getChange())),
        ImmutableSet.of(getUnreviewedLabel(rsrc.getChange())));
  }

  public void markAsUnreviewed(ChangeResource rsrc) throws OrmException, IllegalLabelException {
    star(
        rsrc.getUser().asIdentifiedUser().getAccountId(),
        rsrc.getProject(),
        rsrc.getChange().getId(),
        ImmutableSet.of(getUnreviewedLabel(rsrc.getChange())),
        ImmutableSet.of(getReviewedLabel(rsrc.getChange())));
  }

  public static StarRef readLabels(Repository repo, String refName) throws IOException {
    try (TraceTimer traceTimer = TraceContext.newTimer("Read star labels from %s", refName)) {
      Ref ref = repo.exactRef(refName);
      if (ref == null) {
        return StarRef.MISSING;
      }

      try (ObjectReader reader = repo.newObjectReader()) {
        ObjectLoader obj = reader.open(ref.getObjectId(), Constants.OBJ_BLOB);
        return StarRef.create(
            ref,
            Splitter.on(CharMatcher.whitespace())
                .omitEmptyStrings()
                .split(new String(obj.getCachedBytes(Integer.MAX_VALUE), UTF_8)));
      }
    }
  }

  public static ObjectId writeLabels(Repository repo, Collection<String> labels)
      throws IOException, InvalidLabelsException {
    validateLabels(labels);
    try (ObjectInserter oi = repo.newObjectInserter()) {
      ObjectId id =
          oi.insert(
              Constants.OBJ_BLOB,
              labels.stream().sorted().distinct().collect(joining("\n")).getBytes(UTF_8));
      oi.flush();
      return id;
    }
  }

  private static void checkMutuallyExclusiveLabels(Set<String> labels)
      throws MutuallyExclusiveLabelsException {
    if (labels.containsAll(ImmutableSet.of(DEFAULT_LABEL, IGNORE_LABEL))) {
      throw new MutuallyExclusiveLabelsException(DEFAULT_LABEL, IGNORE_LABEL);
    }

    Set<Integer> reviewedPatchSets = getStarredPatchSets(labels, REVIEWED_LABEL);
    Set<Integer> unreviewedPatchSets = getStarredPatchSets(labels, UNREVIEWED_LABEL);
    Optional<Integer> ps =
        Sets.intersection(reviewedPatchSets, unreviewedPatchSets).stream().findFirst();
    if (ps.isPresent()) {
      throw new MutuallyExclusiveLabelsException(
          getReviewedLabel(ps.get()), getUnreviewedLabel(ps.get()));
    }
  }

  public static Set<Integer> getStarredPatchSets(Set<String> labels, String label) {
    return labels
        .stream()
        .filter(l -> l.startsWith(label + "/"))
        .filter(l -> Ints.tryParse(l.substring(label.length() + 1)) != null)
        .map(l -> Integer.valueOf(l.substring(label.length() + 1)))
        .collect(toSet());
  }

  private static void validateLabels(Collection<String> labels) throws InvalidLabelsException {
    if (labels == null) {
      return;
    }

    SortedSet<String> invalidLabels = new TreeSet<>();
    for (String label : labels) {
      if (CharMatcher.whitespace().matchesAnyOf(label)) {
        invalidLabels.add(label);
      }
    }
    if (!invalidLabels.isEmpty()) {
      throw new InvalidLabelsException(invalidLabels);
    }
  }

  private void updateLabels(
      Repository repo, String refName, ObjectId oldObjectId, Collection<String> labels)
      throws IOException, OrmException, InvalidLabelsException {
    try (TraceTimer traceTimer =
            TraceContext.newTimer("Update star labels in %s (labels=%s)", refName, labels);
        RevWalk rw = new RevWalk(repo)) {
      RefUpdate u = repo.updateRef(refName);
      u.setExpectedOldObjectId(oldObjectId);
      u.setForceUpdate(true);
      u.setNewObjectId(writeLabels(repo, labels));
      u.setRefLogIdent(serverIdent.get());
      u.setRefLogMessage("Update star labels", true);
      RefUpdate.Result result = u.update(rw);
      switch (result) {
        case NEW:
        case FORCED:
        case NO_CHANGE:
        case FAST_FORWARD:
          gitRefUpdated.fire(allUsers, u, null);
          return;
        case IO_FAILURE:
        case LOCK_FAILURE:
        case NOT_ATTEMPTED:
        case REJECTED:
        case REJECTED_CURRENT_BRANCH:
        case RENAMED:
        case REJECTED_MISSING_OBJECT:
        case REJECTED_OTHER_REASON:
        default:
          throw new OrmException(
              String.format("Update star labels on ref %s failed: %s", refName, result.name()));
      }
    }
  }

  private void deleteRef(Repository repo, String refName, ObjectId oldObjectId)
      throws IOException, OrmException {
    if (ObjectId.zeroId().equals(oldObjectId)) {
      // ref doesn't exist
      return;
    }

    try (TraceTimer traceTimer = TraceContext.newTimer("Delete star labels in %s", refName)) {
      RefUpdate u = repo.updateRef(refName);
      u.setForceUpdate(true);
      u.setExpectedOldObjectId(oldObjectId);
      u.setRefLogIdent(serverIdent.get());
      u.setRefLogMessage("Unstar change", true);
      RefUpdate.Result result = u.delete();
      switch (result) {
        case FORCED:
          gitRefUpdated.fire(allUsers, u, null);
          return;
        case NEW:
        case NO_CHANGE:
        case FAST_FORWARD:
        case IO_FAILURE:
        case LOCK_FAILURE:
        case NOT_ATTEMPTED:
        case REJECTED:
        case REJECTED_CURRENT_BRANCH:
        case RENAMED:
        case REJECTED_MISSING_OBJECT:
        case REJECTED_OTHER_REASON:
        default:
          throw new OrmException(
              String.format("Delete star ref %s failed: %s", refName, result.name()));
      }
    }
  }
}
