import com.google.common.flogger.FluentLogger
import com.google.gerrit.entities.Project
import com.google.gerrit.extensions.annotations.Listen
import com.google.gerrit.extensions.annotations.PluginName
import com.google.gerrit.extensions.events.LifecycleListener
import com.google.gerrit.lifecycle.LifecycleModule
import com.google.gerrit.metrics.CallbackMetric1
import com.google.gerrit.metrics.Description
import com.google.gerrit.metrics.Field
import com.google.gerrit.metrics.MetricMaker
import com.google.gerrit.server.config.ConfigUtil
import com.google.gerrit.server.config.PluginConfig
import com.google.gerrit.server.config.PluginConfigFactory
import com.google.gerrit.server.git.GitRepositoryManager
import com.google.gerrit.server.git.WorkQueue
import com.google.gerrit.server.project.ProjectCache
import com.google.inject.Singleton
import org.eclipse.jgit.lib.Repository
import org.h2.store.fs.FileUtils

import javax.inject.Inject
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.ScheduledFuture
import java.util.concurrent.TimeUnit
import java.util.function.BiConsumer
import java.util.regex.Pattern

@Singleton
@Listen
class ProjectsPackedRefsStalenessCheckers implements LifecycleListener {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass()

  @Inject
  @PluginName
  String pluginName
  @Inject
  PluginConfigFactory configFactory
  @Inject
  GitRepositoryManager repoMgr
  @Inject
  ProjectCache projectCache
  @Inject
  WorkQueue workQueue
  @Inject
  RefDbMetrics refdbMetrics

  private ScheduledFuture<?> scheduledCheckerTask
  private String[] projectPrefixes
  private long removeAfter

  def CHECK_INTERVAL_SEC_DEFAULT = 10

  SanitizeProjectName sanitizeProjectName = new SanitizeProjectName()

  @Override
  void start() {
    if (scheduledCheckerTask != null) {
      return;
    }

    PluginConfig pluginConfig = configFactory.getFromGerritConfig(pluginName)
    def checkInterval = pluginConfig.getInt("checkIntervalSec", CHECK_INTERVAL_SEC_DEFAULT)
    projectPrefixes = pluginConfig.getStringList("projectPrefix")
    def staleRemovalTime = pluginConfig.getString("removeAfter")
    removeAfter = staleRemovalTime ? ConfigUtil.getTimeUnit(staleRemovalTime, Long.MAX_VALUE, TimeUnit.MILLISECONDS) : Long.MAX_VALUE

    scheduledCheckerTask = workQueue.getDefaultQueue().scheduleAtFixedRate({ checkProjects() }, checkInterval, checkInterval, TimeUnit.SECONDS)
    logger.atInfo().log("packed-refs.lock staleness checker started for %d projects (checkIntervalSec=%d, projectPrefix=%s)",
     allProjectsToCheck().size(), checkInterval, Arrays.copyOf(projectPrefixes, projectPrefixes.length))
  }

  private def allProjectsToCheck() {
    projectCache.all()
        .collect { it.get() }
        .findAll { String projectName ->
          projectPrefixes.find { projectName.startsWith(it) } != null
        }
  }

  @Override
  void stop() {
    logger.atInfo().log("Stopping all projects staleness checker ...")
    scheduledCheckerTask?.cancel(true)
  }

  def checkProjects() {
    def threadNameOrig = Thread.currentThread().getName()
    try {
      Thread.currentThread().setName("packed-refs.lock checker")
      allProjectsToCheck().each { String projectName ->
        repoMgr.openRepository(Project.nameKey(projectName)).with { Repository it ->
          try {
            recordLockFileAgeMetricAndRemoveIfStale(it, projectName)
          } catch (Exception e) {
            logger.atSevere().withCause(e).log("Error whilst checking project %s", projectName)
          }
        }
      }
    } finally {
      Thread.currentThread().setName(threadNameOrig)
    }
  }

  private void recordLockFileAgeMetricAndRemoveIfStale(Repository repo, String projectName) {
    def repoDir = repo.getDirectory()
    logger.atFine().log("Checking project %s ... ", projectName)
    File packedRefsLock = new File(repoDir, "packed-refs.lock")
    if (!packedRefsLock.exists()) {
      refdbMetrics.projectsAndLockFileAge.put(sanitizeProjectName.sanitize(projectName), 0)
      logger.atFine().log("[%s] lock file didn't exists", projectName)
      return
    }

    def packedRefsLockMillis = FileUtils.lastModified(packedRefsLock.getAbsolutePath())
    def lockFileAge = System.currentTimeMillis() - packedRefsLockMillis
    refdbMetrics.projectsAndLockFileAge.put(sanitizeProjectName.sanitize(projectName), lockFileAge)

    if (lockFileAge > removeAfter) {
      def deleteOk = packedRefsLock.delete()
      logger.atWarning().log("[%s] %s stale lock file (creationMillis=%d, ageMillis=%d): ",
              projectName, deleteOk ? "deleted" : "*FAILED* to delete", packedRefsLockMillis, lockFileAge)
    } else {
      logger.atFine().log("[%s] calculated age for lock file (creationMillis=%d, ageMillis=%d)", projectName, packedRefsLockMillis, lockFileAge)
    }
  }
}

@Singleton
class RefDbMetrics implements LifecycleListener {
  FluentLogger log = FluentLogger.forEnclosingClass()

  @com.google.inject.Inject
  MetricMaker metrics

  CallbackMetric1<String, Long> lockFileAgeMetric
  final Map<String, Long> projectsAndLockFileAge = new ConcurrentHashMap()

  void setupTrigger(CallbackMetric1<String, Long> lockFileAgeMetric, Map<String, Long> projectsAndLockFileAge) {
    metrics.newTrigger(
        lockFileAgeMetric, { ->
      if (projectsAndLockFileAge.isEmpty()) {
        lockFileAgeMetric.forceCreate("")
      } else {
        projectsAndLockFileAge.each { e ->
          lockFileAgeMetric.set(e.key, e.value)
        }
        lockFileAgeMetric.prune()
      }
    })
  }

  CallbackMetric1<String, Long> createCallbackMetric(String name, String description) {
    metrics.newCallbackMetric(
        name,
        Long.class,
        new Description(description).setGauge(),
        Field.ofString("repository_name", { it.projectName } as BiConsumer)
            .description(description)
            .build())
  }

  void start() {
    lockFileAgeMetric = createCallbackMetric("stalefilechecker/stale_file_age_per_project", "Age of lock file")

    setupTrigger(lockFileAgeMetric, projectsAndLockFileAge)
  }

  void stop() {
    lockFileAgeMetric.remove()
  }
}

class PackedStalenessCheckerModule extends LifecycleModule {
  protected void configure() {
    listener().to(RefDbMetrics)
    listener().to(ProjectsPackedRefsStalenessCheckers)
  }
}

class SanitizeProjectName {
  private static final Pattern METRIC_NAME_PATTERN = ~"[a-zA-Z0-9_-]+(/[a-zA-Z0-9_-]+)*"
  private static final Pattern INVALID_CHAR_PATTERN = ~"[^\\w-/]"
  private static final String REPLACEMENT_PREFIX = "_0x"

  static String sanitize(String name) {
    if (METRIC_NAME_PATTERN.matcher(name).matches() && !name.contains(REPLACEMENT_PREFIX)) {
      return name;
    }

    StringBuilder sanitizedName =
        new StringBuilder(name.substring(0, 1).replaceFirst("[^\\w-]", "_"))
    if (name.length() == 1) {
      return sanitizedName.toString()
    }

    String slashSanitizedName = name.substring(1).replaceAll("/[/]+", "/")
    if (slashSanitizedName.endsWith("/")) {
      slashSanitizedName = slashSanitizedName.substring(0, slashSanitizedName.length() - 1)
    }

    String replacementPrefixSanitizedName =
        slashSanitizedName.replaceAll(REPLACEMENT_PREFIX, REPLACEMENT_PREFIX + REPLACEMENT_PREFIX)

    for (int i = 0; i < replacementPrefixSanitizedName.length(); i++) {
      Character c = replacementPrefixSanitizedName.charAt(i)
      if (c.toString() ==~ INVALID_CHAR_PATTERN) {
        sanitizedName.append(REPLACEMENT_PREFIX)
        sanitizedName.append(c.toString().getBytes("UTF-8").encodeHex().toString().toUpperCase())
        sanitizedName.append('_')
      } else {
        sanitizedName.append(c)
      }
    }

    return sanitizedName.toString()
  }
}

modules = [PackedStalenessCheckerModule]
