// 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.notedb;

import static com.google.gerrit.server.update.context.RefUpdateContext.RefUpdateType.CHANGE_MODIFICATION;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.stream.Collectors.toSet;

import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.flogger.FluentLogger;
import com.google.common.primitives.Ints;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.git.GitUpdateFailureException;
import com.google.gerrit.git.LockFailureException;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.StarredChangesUtil;
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.logging.Metadata;
import com.google.gerrit.server.logging.TraceContext;
import com.google.gerrit.server.logging.TraceContext.TraceTimer;
import com.google.gerrit.server.update.context.RefUpdateContext;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
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.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 StarredChangesUtilNoteDbImpl implements StarredChangesUtil {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();
  private static final String DEFAULT_STAR_LABEL = "star";

  private final GitRepositoryManager repoManager;
  private final GitReferenceUpdated gitRefUpdated;
  private final AllUsersName allUsers;
  private final Provider<PersonIdent> serverIdent;

  @Inject
  StarredChangesUtilNoteDbImpl(
      GitRepositoryManager repoManager,
      GitReferenceUpdated gitRefUpdated,
      AllUsersName allUsers,
      @GerritPersonIdent Provider<PersonIdent> serverIdent) {
    this.repoManager = repoManager;
    this.gitRefUpdated = gitRefUpdated;
    this.allUsers = allUsers;
    this.serverIdent = serverIdent;
  }

  @Override
  public boolean isStarred(Account.Id accountId, Change.Id virtualId) {
    try (Repository repo = repoManager.openRepository(allUsers)) {
      return getStarRef(repo, RefNames.refsStarredChanges(virtualId, accountId)).isPresent();
    } catch (IOException e) {
      throw new StorageException(
          String.format(
              "Reading stars from change %d for account %d failed",
              virtualId.get(), accountId.get()),
          e);
    }
  }

  @Override
  public void star(Account.Id accountId, Change.Id virtualId) {
    updateStar(accountId, virtualId, true);
  }

  @Override
  public void unstar(Account.Id accountId, Change.Id virtualId) {
    updateStar(accountId, virtualId, false);
  }

  private void updateStar(Account.Id accountId, Change.Id virtualId, boolean shouldAdd) {
    try (Repository repo = repoManager.openRepository(allUsers)) {
      String refName = RefNames.refsStarredChanges(virtualId, accountId);
      if (shouldAdd) {
        addRef(repo, refName, null);
      } else {
        Optional<Ref> ref = getStarRef(repo, refName);
        if (ref.isPresent()) {
          deleteRef(repo, refName, ref.get().getObjectId());
        }
      }
    } catch (IOException e) {
      throw new StorageException(
          String.format("Star change %d for account %d failed", virtualId.get(), accountId.get()),
          e);
    }
  }

  @Override
  public Set<Change.Id> areStarred(
      Repository allUsersRepo, List<Change.Id> virtualIds, Account.Id caller) {
    List<String> starRefs =
        virtualIds.stream()
            .map(c -> RefNames.refsStarredChanges(c, caller))
            .collect(Collectors.toList());
    try {
      return allUsersRepo.getRefDatabase().exactRef(starRefs.toArray(new String[0])).keySet()
          .stream()
          .map(r -> Change.Id.fromAllUsersRef(r))
          .collect(Collectors.toSet());
    } catch (IOException e) {
      logger.atWarning().withCause(e).log(
          "Failed getting starred changes for account %d within changes: %s",
          caller.get(), Joiner.on(", ").join(virtualIds));
      return ImmutableSet.of();
    }
  }

  @Override
  public void unstarAllForChangeDeletion(Change.Id virtualId) throws IOException {
    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 " + virtualId.get(), true);
      for (Account.Id accountId : getStars(repo, virtualId)) {
        String refName = RefNames.refsStarredChanges(virtualId, accountId);
        Ref ref = repo.getRefDatabase().exactRef(refName);
        if (ref != null) {
          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) {
          String message =
              String.format(
                  "Unstar change %d failed, ref %s could not be deleted: %s",
                  virtualId.get(), command.getRefName(), command.getResult());
          if (command.getResult() == ReceiveCommand.Result.LOCK_FAILURE) {
            throw new LockFailureException(message, batchUpdate);
          }
          throw new GitUpdateFailureException(message, batchUpdate);
        }
      }
    }
  }

  @Override
  public ImmutableMap<Account.Id, Ref> byChange(Change.Id virtualId) {
    try (Repository repo = repoManager.openRepository(allUsers)) {
      ImmutableMap.Builder<Account.Id, Ref> builder = ImmutableMap.builder();
      for (Account.Id accountId : getStars(repo, virtualId)) {
        Optional<Ref> starRef = getStarRef(repo, RefNames.refsStarredChanges(virtualId, accountId));
        if (starRef.isPresent()) {
          builder.put(accountId, starRef.get());
        }
      }
      return builder.build();
    } catch (IOException e) {
      throw new StorageException(
          String.format("Get accounts that starred change %d failed", virtualId.get()), e);
    }
  }

  @Override
  public ImmutableSet<Change.Id> byAccountId(Account.Id accountId) {
    return byAccountId(accountId, true);
  }

  @Override
  public ImmutableSet<Change.Id> byAccountId(Account.Id accountId, boolean skipInvalidChanges) {
    try (Repository repo = repoManager.openRepository(allUsers)) {
      ImmutableSet.Builder<Change.Id> builder = ImmutableSet.builder();
      for (Ref ref : repo.getRefDatabase().getRefsByPrefix(RefNames.REFS_STARRED_CHANGES)) {
        Account.Id currentAccountId = Account.Id.fromRef(ref.getName());
        // Skip all refs that don't correspond with accountId.
        if (currentAccountId == null || !currentAccountId.equals(accountId)) {
          continue;
        }

        // Skip invalid change ids.
        Change.Id changeId = Change.Id.fromAllUsersRef(ref.getName());
        if (skipInvalidChanges && changeId == null) {
          continue;
        }
        builder.add(changeId);
      }
      return builder.build();
    } catch (IOException e) {
      throw new StorageException(
          String.format("Get starred changes for account %d failed", accountId.get()), e);
    }
  }

  private static Set<Account.Id> getStars(Repository allUsers, Change.Id virtualId)
      throws IOException {
    String prefix = RefNames.refsStarredChangesPrefix(virtualId);
    RefDatabase refDb = allUsers.getRefDatabase();
    return refDb.getRefsByPrefix(prefix).stream()
        .map(r -> r.getName().substring(prefix.length()))
        .map(refPart -> Ints.tryParse(refPart))
        .filter(Objects::nonNull)
        .map(id -> Account.id(id))
        .collect(toSet());
  }

  private static Optional<Ref> getStarRef(Repository repo, @Nullable String refName)
      throws IOException {
    if (refName == null) {
      return Optional.empty();
    }
    Ref ref = repo.exactRef(refName);
    return Optional.ofNullable(ref);
  }

  private static ObjectId writeStarredRefContent(Repository repo) throws IOException {
    try (ObjectInserter oi = repo.newObjectInserter()) {
      ObjectId id = oi.insert(Constants.OBJ_BLOB, DEFAULT_STAR_LABEL.getBytes(UTF_8));
      oi.flush();
      return id;
    }
  }

  private void addRef(Repository repo, String refName, ObjectId oldObjectId) throws IOException {
    try (TraceTimer traceTimer =
            TraceContext.newTimer(
                "Add star ref",
                Metadata.builder().noteDbRefName(refName).resourceCount(1).build());
        RevWalk rw = new RevWalk(repo)) {
      RefUpdate u = repo.updateRef(refName);
      u.setExpectedOldObjectId(oldObjectId);
      u.setForceUpdate(true);
      u.setNewObjectId(writeStarredRefContent(repo));
      u.setRefLogIdent(serverIdent.get());
      u.setRefLogMessage("Add star ref", true);
      try (RefUpdateContext ctx = RefUpdateContext.open(CHANGE_MODIFICATION)) {
        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 LOCK_FAILURE:
            throw new LockFailureException(
                String.format("Add star ref on ref %s failed", refName), u);
          case IO_FAILURE:
          case NOT_ATTEMPTED:
          case REJECTED:
          case REJECTED_CURRENT_BRANCH:
          case RENAMED:
          case REJECTED_MISSING_OBJECT:
          case REJECTED_OTHER_REASON:
          default:
            throw new StorageException(
                String.format("Add star ref on ref %s failed: %s", refName, result.name()));
        }
      }
    }
  }

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

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