package com.airlock.iam.configeditor.shared.application;

import com.airlock.iam.elog.api.ELogger;
import com.airlock.iam.elog.api.ELoggerFactory;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.time.Duration;
import java.util.Arrays;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;

public final class ConfigEditorProperties {
   private static final ELogger LOG = ELoggerFactory.getLogger(ConfigEditorProperties.class);
   private static final ConfigEditorProperties DEFAULT_INSTANCE = new ConfigEditorProperties(System.getProperties());
   private final Map<ConfigEditorProperties.ConfigEditorProperty, String> properties;

   public static ConfigEditorProperties configEditorProperties() {
      return DEFAULT_INSTANCE;
   }

   @VisibleForTesting
   @SuppressFBWarnings("SING_SINGLETON_HAS_NONPRIVATE_CONSTRUCTOR")
   ConfigEditorProperties(Properties systemProperties) {
      this.properties = loadConfigEditorProperties(systemProperties);
   }

   public Duration getActivationTimeout() {
      return Duration.ofSeconds(Long.parseLong(this.properties.get(ConfigEditorProperties.ConfigEditorProperty.ACTIVATION_TIMEOUT)));
   }

   public boolean getValidationDefault() {
      return Boolean.parseBoolean(this.properties.get(ConfigEditorProperties.ConfigEditorProperty.VALIDATION_DEFAULT));
   }

   public boolean getPluginTrackingDefault() {
      return Boolean.parseBoolean(this.properties.get(ConfigEditorProperties.ConfigEditorProperty.PLUGIN_TRACKING_DEFAULT));
   }

   public boolean isShowVariables() {
      return Boolean.parseBoolean(this.properties.get(ConfigEditorProperties.ConfigEditorProperty.SHOW_VARIABLES));
   }

   private static Map<ConfigEditorProperties.ConfigEditorProperty, String> loadConfigEditorProperties(Properties systemProperties) {
      Map<ConfigEditorProperties.ConfigEditorProperty, String> configEditorProperties = Arrays.stream(ConfigEditorProperties.ConfigEditorProperty.values())
         .collect(Collectors.toMap(Function.identity(), p -> getProperty(systemProperties, p)));
      LOG.debug("Loaded config editor properties: " + Joiner.on(",").withKeyValueSeparator("=").join(configEditorProperties));
      return configEditorProperties;
   }

   private static String getProperty(Properties properties, ConfigEditorProperties.ConfigEditorProperty property) {
      return Optional.ofNullable(properties.getProperty(property.key())).<String>map(StringUtils::trimToNull).orElse(property.defaultValue());
   }

   enum ConfigEditorProperty {
      ACTIVATION_TIMEOUT("iam.config-editor.activation.timeout", "20"),
      VALIDATION_DEFAULT("iam.config-editor.validation.default", "true"),
      PLUGIN_TRACKING_DEFAULT("iam.config-editor.plugin-tracking.default", "false"),
      SHOW_VARIABLES("iam.config-editor.show-variables", "false");

      private final String key;
      private final String defaultValue;

      ConfigEditorProperty(String key, String defaultValue) {
         this.key = key;
         this.defaultValue = defaultValue;
      }

      public String key() {
         return this.key;
      }

      public String defaultValue() {
         return this.defaultValue;
      }
   }
}
