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

import static com.google.common.base.Preconditions.checkNotNull;
import static com.googlesource.gerrit.plugins.healthcheck.check.HealthCheckNames.QUERYCHANGES;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.MoreObjects;
import com.google.common.base.Strings;
import com.google.gerrit.entities.Project;
import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.server.config.AllProjectsName;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.config.GerritIsReplica;
import com.google.gerrit.server.config.PluginConfigFactory;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.util.Collections;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Config;

@Singleton
public class HealthCheckConfig {
  public static final String HEALTHCHECK = "healthcheck";
  public static final HealthCheckConfig DEFAULT_CONFIG = new HealthCheckConfig(null);
  private static final long HEALTHCHECK_TIMEOUT_DEFAULT = 500L;
  private static final String QUERY_DEFAULT = "status:open";
  private static final int LIMIT_DEFAULT = 10;
  private static final int ACTIVE_WORKERS_THRESHOLD_DEFAULT = 80;
  private static final String USERNAME_DEFAULT = "healthcheck";
  private static final String PASSWORD_DEFAULT = "";
  private static final boolean HEALTH_CHECK_ENABLED_DEFAULT = true;
  private final AllProjectsName allProjectsName;
  private final AllUsersName allUsersName;

  private final Config config;
  private final boolean isReplica;

  private static final Set<String> HEALTH_CHECK_DISABLED_FOR_REPLICAS =
      Collections.singleton(QUERYCHANGES);

  @Inject
  public HealthCheckConfig(
      PluginConfigFactory configFactory,
      @PluginName String pluginName,
      AllProjectsName allProjectsName,
      AllUsersName allUsersName,
      @GerritIsReplica boolean isReplica) {
    config = configFactory.getGlobalPluginConfig(pluginName);
    this.allProjectsName = allProjectsName;
    this.allUsersName = allUsersName;
    this.isReplica = isReplica;
  }

  @VisibleForTesting
  HealthCheckConfig(String configText) {
    config = new Config();
    if (!Strings.isNullOrEmpty(configText)) {
      try {
        config.fromText(configText);
      } catch (ConfigInvalidException e) {
        throw new IllegalArgumentException("Invalid configuration " + configText, e);
      }
    }
    allProjectsName = new AllProjectsName("All-Projects");
    allUsersName = new AllUsersName("All-Users");
    isReplica = false;
  }

  @VisibleForTesting
  void fromText(String configText) throws ConfigInvalidException {
    config.fromText(configText);
  }

  public long getTimeout() {
    return getTimeout(null);
  }

  public long getTimeout(String healthCheckName) {
    long defaultTimeout = healthCheckName == null ? HEALTHCHECK_TIMEOUT_DEFAULT : getTimeout(null);
    return config.getTimeUnit(
        HEALTHCHECK, healthCheckName, "timeout", defaultTimeout, TimeUnit.MILLISECONDS);
  }

  public String getQuery(String healthCheckName) {
    return getStringWithFallback("query", healthCheckName, QUERY_DEFAULT);
  }

  public int getLimit(String healthCheckName) {
    int defaultLimit = healthCheckName == null ? LIMIT_DEFAULT : getLimit(null);
    return config.getInt(HEALTHCHECK, healthCheckName, "limit", defaultLimit);
  }

  public int getActiveWorkersThreshold(String healthCheckName) {
    int defaultThreshold =
        healthCheckName == null
            ? ACTIVE_WORKERS_THRESHOLD_DEFAULT
            : getActiveWorkersThreshold(null);
    return config.getInt(HEALTHCHECK, healthCheckName, "threshold", defaultThreshold);
  }

  public Set<Project.NameKey> getJGITRepositories(String healthCheckName) {
    Set<Project.NameKey> repos =
        Stream.of(config.getStringList(HEALTHCHECK, healthCheckName, "project"))
            .map(Project::nameKey)
            .collect(Collectors.toSet());
    repos.add(allProjectsName);
    repos.add(allUsersName);
    return repos;
  }

  public String getUsername(String healthCheckName) {
    return getStringWithFallback("username", healthCheckName, USERNAME_DEFAULT);
  }

  public String getPassword(String healthCheckName) {
    return getStringWithFallback("password", healthCheckName, PASSWORD_DEFAULT);
  }

  public boolean healthCheckEnabled(String healthCheckName) {
    if (isReplica && HEALTH_CHECK_DISABLED_FOR_REPLICAS.contains(healthCheckName)) {
      return false;
    }
    return config.getBoolean(
        HEALTHCHECK, checkNotNull(healthCheckName), "enabled", HEALTH_CHECK_ENABLED_DEFAULT);
  }

  private String getStringWithFallback(
      String parameter, String healthCheckName, String defaultValue) {
    String fallbackDefault =
        healthCheckName == null
            ? defaultValue
            : getStringWithFallback(parameter, null, defaultValue);
    return MoreObjects.firstNonNull(
        config.getString(HEALTHCHECK, healthCheckName, parameter), fallbackDefault);
  }
}
