// 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.googlesource.gerrit.plugins.multisite.validation;

import com.gerritforge.gerrit.globalrefdb.GlobalRefDbLockException;
import com.gerritforge.gerrit.globalrefdb.validation.SharedRefDatabaseWrapper;
import com.google.common.base.Preconditions;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.entities.Project;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.googlesource.gerrit.plugins.multisite.Configuration;
import com.googlesource.gerrit.plugins.replication.ReplicationPushFilter;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectIdRef;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.transport.RemoteRefUpdate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Singleton
public class MultisiteReplicationPushFilter implements ReplicationPushFilter {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();
  private static final String REF_META_SUFFIX = "/meta";

  static final String REPLICATION_LOG_NAME = "replication_log";
  static final Logger repLog = LoggerFactory.getLogger(REPLICATION_LOG_NAME);

  private final SharedRefDatabaseWrapper sharedRefDb;
  private final GitRepositoryManager gitRepositoryManager;
  private Configuration config;

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

  @Override
  public List<RemoteRefUpdate> filter(String projectName, List<RemoteRefUpdate> remoteUpdatesList) {
    Set<String> outdatedChanges = new HashSet<>();

    try (Repository repository =
        gitRepositoryManager.openRepository(Project.nameKey(projectName))) {
      List<RemoteRefUpdate> filteredRefUpdates =
          remoteUpdatesList.stream()
              .map(
                  refUpdate -> {
                    Optional<RemoteRefUpdate> updatedRefUpdate =
                        isUpToDateWithRetry(projectName, repository, refUpdate);
                    if (!updatedRefUpdate.isPresent()) {
                      repLog.warn(
                          "{} is not up-to-date with the shared-refdb and thus will NOT BE"
                              + " replicated",
                          refUpdate);
                      if (refUpdate.getSrcRef().endsWith(REF_META_SUFFIX)) {
                        outdatedChanges.add(getRootChangeRefPrefix(refUpdate.getSrcRef()));
                      }
                    }
                    return updatedRefUpdate;
                  })
              .filter(Optional::isPresent)
              .map(Optional::get)
              .collect(Collectors.toList());

      return filteredRefUpdates.stream()
          .filter(
              refUpdate -> {
                if (outdatedChanges.contains(changePrefix(refUpdate.getSrcRef()))) {
                  repLog.warn(
                      "{} belongs to an outdated /meta ref and thus will NOT BE replicated",
                      refUpdate);
                  return false;
                }
                return true;
              })
          .collect(Collectors.toList());

    } catch (IOException ioe) {
      final String messageFmt = "Error while opening project: '%s'";
      repLog.error(messageFmt, projectName);
      logger.atSevere().withCause(ioe).log(messageFmt, projectName);
      return Collections.emptyList();
    }
  }

  private Optional<RemoteRefUpdate> isUpToDateWithRetry(
      String projectName, Repository repository, RemoteRefUpdate refUpdate) {
    String ref = refUpdate.getSrcRef();
    try {
      if (sharedRefDb.isUpToDate(
          Project.nameKey(projectName),
          new ObjectIdRef.Unpeeled(Ref.Storage.NETWORK, ref, refUpdate.getNewObjectId()))) {
        return Optional.of(refUpdate);
      }

      randomSleepForMitigatingConditionWhereLocalRefHaveJustBeenChanged(
          projectName, refUpdate, ref);

      ObjectId reloadedNewObjectId = getNotNullExactRef(repository, ref);
      RemoteRefUpdate refUpdateReloaded =
          newRemoteRefUpdateWithObjectId(repository, refUpdate, reloadedNewObjectId);
      return sharedRefDb.isUpToDate(
              Project.nameKey(projectName),
              new ObjectIdRef.Unpeeled(
                  Ref.Storage.NETWORK, ref, refUpdateReloaded.getNewObjectId()))
          ? Optional.of(refUpdateReloaded)
          : Optional.empty();
    } catch (GlobalRefDbLockException gle) {
      final String messageFmt = "%s is locked on shared-refdb and thus will NOT BE replicated";
      repLog.error(messageFmt, ref);
      logger.atSevere().withCause(gle).log(messageFmt, ref);
      return Optional.empty();
    } catch (IOException ioe) {
      final String messageFmt = "Error while extracting ref '%s' for project '%s'";
      repLog.error(messageFmt, ref, projectName);
      logger.atSevere().withCause(ioe).log(messageFmt, ref, projectName);
      return Optional.empty();
    }
  }

  private RemoteRefUpdate newRemoteRefUpdateWithObjectId(
      Repository localDb, RemoteRefUpdate refUpdate, ObjectId reloadedNewObjectId)
      throws IOException {
    return new RemoteRefUpdate(
        localDb,
        refUpdate.getSrcRef(),
        reloadedNewObjectId,
        refUpdate.getRemoteName(),
        refUpdate.isForceUpdate(),
        null,
        refUpdate.getExpectedOldObjectId());
  }

  private void randomSleepForMitigatingConditionWhereLocalRefHaveJustBeenChanged(
      String projectName, RemoteRefUpdate refUpdate, String ref) {
    if (!config.replicationFilter().isPushFilterRandomSleepEnabled()) {
      return;
    }

    int randomSleepTimeMsec = config.replicationFilter().pushFilterRandomSleepTimeMs();
    repLog.debug(
        String.format(
            "'%s' is not up-to-date for project '%s' [local='%s']. Reload local ref in '%d ms' and"
                + " re-check",
            ref, projectName, refUpdate.getNewObjectId(), randomSleepTimeMsec));
    try {
      Thread.sleep(randomSleepTimeMsec);
    } catch (InterruptedException ie) {
      final String messageFmt = "Error while waiting for next check for '%s', ref '%s'";
      repLog.error(messageFmt, projectName, ref);
      logger.atWarning().withCause(ie).log(messageFmt, projectName, ref);
    }
  }

  private String changePrefix(String changeRef) {
    if (changeRef == null || !changeRef.startsWith("refs/changes")) {
      return changeRef;
    }
    if (changeRef.endsWith(REF_META_SUFFIX)) {
      return getRootChangeRefPrefix(changeRef);
    }

    // changeRef has the form '/refs/changes/NN/NNNN/P'
    return changeRef.substring(0, changeRef.lastIndexOf('/'));
  }

  private String getRootChangeRefPrefix(String changeMetaRef) {
    if (changeMetaRef.endsWith(REF_META_SUFFIX)) {
      return changeMetaRef.substring(0, changeMetaRef.length() - REF_META_SUFFIX.length());
    }

    return changeMetaRef;
  }

  private ObjectId getNotNullExactRef(Repository repository, String refName) throws IOException {
    Ref ref = repository.exactRef(refName);
    Preconditions.checkNotNull(ref);
    return ref.getObjectId();
  }
}
