// Copyright (C) 2020 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.multisite.validation;

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;

import com.gerritforge.gerrit.globalrefdb.GlobalRefDbSystemError;
import com.google.common.base.CharMatcher;
import com.google.common.collect.ImmutableSet;
import com.google.common.flogger.FluentLogger;
import com.google.common.primitives.Ints;
import com.google.gerrit.entities.Project;
import com.google.gerrit.server.events.Event;
import com.google.gerrit.server.events.EventListener;
import com.google.gerrit.server.events.RefUpdatedEvent;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.notedb.IntBlob;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.googlesource.gerrit.plugins.multisite.SharedRefDatabaseWrapper;
import com.googlesource.gerrit.plugins.multisite.forwarder.Context;
import com.googlesource.gerrit.plugins.replication.RefReplicatedEvent;
import java.io.IOException;
import java.util.Optional;
import java.util.Set;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectIdRef;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.RemoteRefUpdate;

@Singleton
public class ProjectVersionRefUpdate implements EventListener {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();
  public static final String MULTI_SITE_VERSIONING_REF = "refs/multi-site/version";
  public static final String SEQUENCE_REF_PREFIX = "refs/sequences/";
  private static final Ref NULL_PROJECT_VERSION_REF =
      new ObjectIdRef.Unpeeled(Ref.Storage.NETWORK, MULTI_SITE_VERSIONING_REF, ObjectId.zeroId());
  private static final Set<RefUpdate.Result> SUCCESSFUL_RESULTS =
      ImmutableSet.of(RefUpdate.Result.NEW, RefUpdate.Result.FORCED, RefUpdate.Result.NO_CHANGE);

  protected final SharedRefDatabaseWrapper sharedRefDb;
  private final GitRepositoryManager gitRepositoryManager;

  @Inject
  public ProjectVersionRefUpdate(
      GitRepositoryManager gitRepositoryManager, SharedRefDatabaseWrapper sharedRefDb) {
    this.gitRepositoryManager = gitRepositoryManager;
    this.sharedRefDb = sharedRefDb;
  }

  @Override
  public void onEvent(Event event) {
    logger.atFine().log("Processing event type: " + event.type);
    // Producer of the Event use RefUpdatedEvent to trigger the version update
    if (!Context.isForwardedEvent() && event instanceof RefUpdatedEvent) {
      updateProducerProjectVersionUpdate((RefUpdatedEvent) event);
    }

    // Consumers of the Event use RefReplicatedEvent to trigger the version update
    if (Context.isForwardedEvent() && event instanceof RefReplicatedEvent) {
      updateConsumerProjectVersion((RefReplicatedEvent) event);
    }
  }

  private void updateConsumerProjectVersion(RefReplicatedEvent refReplicatedEvent) {
    Project.NameKey projectNameKey = refReplicatedEvent.getProjectNameKey();
    if (!refReplicatedEvent.refStatus.equals(RemoteRefUpdate.Status.OK)) {
      logger.atFine().log(
          String.format(
              "Skipping version update for %s. RefReplicatedEvent failed with %s",
              projectNameKey.get(), refReplicatedEvent.refStatus));
      return;
    }
    if (refReplicatedEvent.getRefName().startsWith(SEQUENCE_REF_PREFIX)) {
      logger.atFine().log("Found Sequence ref, skipping update for " + projectNameKey.get());
      return;
    }
    try {
      updateLocalProjectVersion(projectNameKey, refReplicatedEvent.getRefName());
    } catch (LocalProjectVersionUpdateException e) {
      logger.atSevere().withCause(e).log(
          "Issue encountered when updating version for project " + projectNameKey);
    }
  }

  private void updateProducerProjectVersionUpdate(RefUpdatedEvent refUpdatedEvent) {
    if (refUpdatedEvent.getRefName().startsWith(SEQUENCE_REF_PREFIX)) {
      logger.atFine().log(
          "Found Sequence ref, skipping update for " + refUpdatedEvent.getProjectNameKey().get());
      return;
    }
    try {
      Project.NameKey projectNameKey = refUpdatedEvent.getProjectNameKey();
      Ref currentProjectVersionRef = getLocalProjectVersionRef(refUpdatedEvent.getProjectNameKey());
      ObjectId newProjectVersionObjectId =
          updateLocalProjectVersion(projectNameKey, refUpdatedEvent.getRefName());
      updateSharedProjectVersion(
          projectNameKey, currentProjectVersionRef, newProjectVersionObjectId);
    } catch (LocalProjectVersionUpdateException | SharedProjectVersionUpdateException e) {
      logger.atSevere().withCause(e).log(
          "Issue encountered when updating version for project "
              + refUpdatedEvent.getProjectNameKey());
    }
  }

  private RefUpdate getProjectVersionRefUpdate(Repository repository, Long version)
      throws IOException {
    RefUpdate refUpdate = repository.getRefDatabase().newUpdate(MULTI_SITE_VERSIONING_REF, false);
    refUpdate.setNewObjectId(getNewId(repository, version));
    refUpdate.setForceUpdate(true);
    return refUpdate;
  }

  private ObjectId getNewId(Repository repository, Long version) throws IOException {
    ObjectInserter ins = repository.newObjectInserter();
    ObjectId newId = ins.insert(OBJ_BLOB, Long.toString(version).getBytes(UTF_8));
    ins.flush();
    return newId;
  }

  private Ref getLocalProjectVersionRef(Project.NameKey projectNameKey)
      throws LocalProjectVersionUpdateException {
    try (Repository repository = gitRepositoryManager.openRepository(projectNameKey)) {
      Ref ref = repository.findRef(MULTI_SITE_VERSIONING_REF);
      return ref != null ? ref : NULL_PROJECT_VERSION_REF;
    } catch (IOException e) {
      String message =
          String.format("Error while getting current version for %s", projectNameKey.get());
      logger.atSevere().withCause(e).log(message);
      throw new LocalProjectVersionUpdateException(message);
    }
  }

  private Long getLastRefUpdatedTimestamp(Project.NameKey projectNameKey, String refName)
      throws LocalProjectVersionUpdateException {
    logger.atFine().log(
        String.format(
            "Getting last ref updated time for project %s, ref %s", projectNameKey.get(), refName));
    try (Repository repository = gitRepositoryManager.openRepository(projectNameKey)) {
      Ref ref = repository.findRef(refName);
      try (RevWalk walk = new RevWalk(repository)) {
        RevCommit commit = walk.parseCommit(ref.getObjectId());
        return Integer.toUnsignedLong(commit.getCommitTime());
      }
    } catch (IOException ioe) {
      String message =
          String.format(
              "Error while getting last ref updated time for project %s, ref %s",
              projectNameKey.get(), refName);
      logger.atSevere().withCause(ioe).log(message);
      throw new LocalProjectVersionUpdateException(message);
    }
  }

  private void updateSharedProjectVersion(
      Project.NameKey projectNameKey, Ref currentRef, ObjectId newObjectId)
      throws SharedProjectVersionUpdateException {
    logger.atFine().log(
        String.format(
            "Updating shared project version for %s. Current value %s, new value: %s",
            projectNameKey.get(), currentRef.getObjectId(), newObjectId));
    try {
      boolean success = sharedRefDb.compareAndPut(projectNameKey, currentRef, newObjectId);
      String message =
          String.format(
              "Project version update failed for %s. Current value %s, new value: %s",
              projectNameKey.get(), currentRef.getObjectId(), newObjectId);
      if (!success) {
        logger.atSevere().log(message);
        throw new SharedProjectVersionUpdateException(message);
      }
    } catch (GlobalRefDbSystemError refDbSystemError) {
      String message =
          String.format(
              "Error while updating shared project version for %s. Current value %s, new value: %s. Error: %s",
              projectNameKey.get(),
              currentRef.getObjectId(),
              newObjectId,
              refDbSystemError.getMessage());
      logger.atSevere().withCause(refDbSystemError).log(message);
      throw new SharedProjectVersionUpdateException(message);
    }
  }

  public Optional<Long> getProjectLocalVersion(String projectName) {
    try (Repository repository =
        gitRepositoryManager.openRepository(Project.NameKey.parse(projectName))) {
      Optional<IntBlob> blob = IntBlob.parse(repository, MULTI_SITE_VERSIONING_REF);
      if (blob.isPresent()) {
        Long repoVersion = Integer.toUnsignedLong(blob.get().value());
        logger.atInfo().log("Local project '%s' has version %d", projectName, repoVersion);
        return Optional.of(repoVersion);
      }
    } catch (IOException e) {
      logger.atSevere().withCause(e).log("Cannot read local project '%s' version", projectName);
    }
    return Optional.empty();
  }

  public Optional<Long> getProjectRemoteVersion(String projectName) {
    Optional<ObjectId> remoteObjectId =
        sharedRefDb.get(
            Project.NameKey.parse(projectName), MULTI_SITE_VERSIONING_REF, ObjectId.class);
    if (remoteObjectId.isPresent()) {
      return getLongFromObjectId(projectName, remoteObjectId.get());
    } else {
      logger.atSevere().log("Didn't find remote version for %s", projectName);
      return Optional.empty();
    }
  }

  private Optional<Long> getLongFromObjectId(String projectName, ObjectId objectId) {
    try (Repository repository =
        gitRepositoryManager.openRepository(Project.NameKey.parse(projectName))) {
      ObjectReader or = repository.newObjectReader();
      ObjectLoader ol = or.open(objectId, OBJ_BLOB);
      if (ol.getType() != OBJ_BLOB) {
        // In theory this should be thrown by open but not all implementations may do it properly
        // (certainly InMemoryRepository doesn't).
        logger.atSevere().log("Incorrect object type loaded for objectId %s", objectId.toString());
        return Optional.empty();
      }
      String str = CharMatcher.whitespace().trimFrom(new String(ol.getCachedBytes(), UTF_8));
      Integer value = Ints.tryParse(str);
      logger.atInfo().log(
          "Found remote version for project %s, value: %s - %d",
          projectName, objectId.toString(), value);
      return Optional.of(Integer.toUnsignedLong(value));
    } catch (IOException e) {
      logger.atSevere().withCause(e).log("Cannot parse objectId %s", objectId.toString());
      return Optional.empty();
    }
  }

  private ObjectId updateLocalProjectVersion(Project.NameKey projectNameKey, String refName)
      throws LocalProjectVersionUpdateException {
    Long lastRefUpdatedTimestamp = getLastRefUpdatedTimestamp(projectNameKey, refName);
    logger.atFine().log("Updating local version for project " + projectNameKey.get());
    try (Repository repository = gitRepositoryManager.openRepository(projectNameKey)) {
      RefUpdate refUpdate = getProjectVersionRefUpdate(repository, lastRefUpdatedTimestamp);
      RefUpdate.Result result = refUpdate.update();
      if (!isSuccessful(result)) {
        String message =
            String.format(
                "RefUpdate failed with result %s for: project=%s, version=%d",
                result.name(), projectNameKey.get(), lastRefUpdatedTimestamp);
        logger.atSevere().log(message);
        throw new LocalProjectVersionUpdateException(message);
      }
      return refUpdate.getNewObjectId();
    } catch (IOException e) {
      String message = "Cannot create versioning command for " + projectNameKey.get();
      logger.atSevere().withCause(e).log(message);
      throw new LocalProjectVersionUpdateException(message);
    }
  }

  private Boolean isSuccessful(RefUpdate.Result result) {
    return SUCCESSFUL_RESULTS.contains(result);
  }

  public static class LocalProjectVersionUpdateException extends Exception {
    public LocalProjectVersionUpdateException(String projectName) {
      super("Cannot update local project version of " + projectName);
    }
  }

  public static class SharedProjectVersionUpdateException extends Exception {
    public SharedProjectVersionUpdateException(String projectName) {
      super("Cannot update shared project version of " + projectName);
    }
  }
}
