package com.airlock.iam.application.parameters.domain.model;

import java.util.Locale;
import java.util.NoSuchElementException;
import java.util.regex.Pattern;
import java.util.stream.Stream;

public enum ParameterSpec {
   JAVA_OPTS("iam.java.opts"),
   WORK_DIR("iam.workdir"),
   PID_FILE("iam.pid-file"),
   PLUGIN_CONFIG("iam.config"),
   PLUGIN_CONFIG_FORMAT("iam.config.format"),
   ACTIVATED_CONFIGS_DIR("iam.activated-configs.dir", true),
   LICENSE("iam.license"),
   MODULES("iam.modules"),
   ENVIRONMENT_ID("iam.environment.id"),
   SENSITIVE_VALUES_CONFIG("iam.sensitive-values.config"),
   MODE("iam.mode"),
   WEB_SERVER_CONNECTORS("iam.web-server.connectors"),
   WEB_SERVER_MAX_HTTP_HEADER_SIZE("iam.web-server.header.bytes.max"),
   WEB_SERVER_COMPRESSION("iam.web-server.compression.enabled"),
   WEB_SERVER_MAX_THREADS("iam.web-server.threads.max"),
   WEB_SERVER_HTTP_ADDRESS("iam.web-server.http.address"),
   WEB_SERVER_HTTP_PORT("iam.web-server.http.port"),
   WEB_SERVER_HTTPS_ADDRESS("iam.web-server.https.address"),
   WEB_SERVER_HTTPS_PORT("iam.web-server.https.port"),
   WEB_SERVER_HTTPS_TLS_PROTOCOLS("iam.web-server.https.tls-protocols"),
   WEB_SERVER_HTTPS_TLS_CIPHERS("iam.web-server.https.ciphers"),
   WEB_SERVER_HTTPS_KEYSTORE_TYPE("iam.web-server.https.keystore.type"),
   WEB_SERVER_HTTPS_KEYSTORE_FILE("iam.web-server.https.keystore.file"),
   WEB_SERVER_HTTPS_KEYSTORE_PASSWORD("iam.web-server.https.keystore.password"),
   WEB_SERVER_HTTPS_TRUSTSTORE_TYPE("iam.web-server.https.truststore.type"),
   WEB_SERVER_HTTPS_TRUSTSTORE_FILE("iam.web-server.https.truststore.file"),
   WEB_SERVER_HTTPS_TRUSTSTORE_PASSWORD("iam.web-server.https.truststore.password"),
   WEB_SERVER_HTTPS_CLIENTAUTH("iam.web-server.https.client-auth"),
   LOG_LEVEL("iam.log.level"),
   LOG_LABEL("iam.log.label"),
   LOG_MAIN_ENABLED("iam.log.main.enabled"),
   LOG_MAIN_DIR("iam.log.main.dir"),
   LOG_MAIN_ROTATE_MAX_DAYS("iam.log.main.rotate.max-days"),
   LOG_MAIN_PATTERN("iam.log.main.pattern"),
   LOG_STRUCTURED_STDOUT_ENABLED("iam.log.structured-stdout.enabled"),
   LOG_STRUCTURED_FILE_ENABLED("iam.log.structured-file.enabled"),
   LOG_STRUCTURED_FILE_DIR("iam.log.structured-file.dir"),
   LOG_STRUCTURED_FILE_ROTATE_MAX_DAYS("iam.log.structured-file.rotate.max-days"),
   LOG_ELASTICSEARCH_URL("iam.log.elasticsearch.url"),
   WEB_SERVER_LOG_FILE_ENABLED("iam.web-server.log.file.enabled"),
   WEB_SERVER_LOG_STRUCTURED_FILE_ENABLED("iam.web-server.log.structured-file.enabled"),
   WEB_SERVER_LOG_CONSOLE_ENABLED("iam.web-server.log.console.enabled"),
   WEB_SERVER_LOG_DIR("iam.web-server.log.dir"),
   WEB_SERVER_LOG_FILE_PREFIX("iam.web-server.log.file.prefix"),
   WEB_SERVER_LOG_FILE_SUFFIX("iam.web-server.log.file.suffix"),
   WEB_SERVER_LOG_ROTATE_MAX_DAYS("iam.web-server.log.rotate.max-days"),
   WEB_SERVER_LOG_CONSOLE_FORMAT("iam.web-server.log.console.format"),
   WEB_SERVER_LOG_PATTERN("iam.web-server.log.format.simple.pattern"),
   WEB_SERVER_LOG_CONSOLE_LEVEL("iam.web-server.log.console.level"),
   WEB_SERVER_LOG_FILE_LEVEL("iam.web-server.log.file.level"),
   WEB_SERVER_ACCESS_LOG_FILE_ENABLED("iam.web-server.access-log.file.enabled"),
   WEB_SERVER_ACCESS_LOG_STRUCTURED_FILE_ENABLED("iam.web-server.access-log.structured-file.enabled"),
   WEB_SERVER_ACCESS_LOG_CONSOLE_ENABLED("iam.web-server.access-log.console.enabled"),
   WEB_SERVER_ACCESS_LOG_DIR("iam.web-server.access-log.dir"),
   WEB_SERVER_ACCESS_LOG_FILE_PREFIX("iam.web-server.access-log.file.prefix"),
   WEB_SERVER_ACCESS_LOG_FILE_SUFFIX("iam.web-server.access-log.file.suffix"),
   WEB_SERVER_ACCESS_LOG_ROTATE_MAX_DAYS("iam.web-server.access-log.rotate.max-days"),
   WEB_SERVER_ACCESS_LOG_PATTERN("iam.web-server.access-log.format.simple.pattern"),
   AUDIT_LOG_SIGNING_ENABLED("iam.audit-log.signing.enabled"),
   AUDIT_LOG_SIGNING_CONFIG("iam.audit-log.signing.config"),
   ADMINAPP_URL_PATH("iam.adminapp.url.path"),
   ADMINAPP_APPLICATION_LISTENER("iam.adminapp.application.listener"),
   ADMINAPP_CLASSPATH("iam.internal.adminapp.classpath"),
   ADMINAPP_CLASSPATH_EXT("iam.adminapp.classpath.ext"),
   ADMINAPP_LOG4J_CONFIGS("iam.adminapp.log4j.configs"),
   ADMINAPP_LAYOUT_DIRS("iam.adminapp.layout.dirs"),
   OLD_CONFIG_EDITOR_ENABLED("iam.config-editor.enabled"),
   OLD_CONFIG_EDITOR_STANDALONE("iam.config-editor.standalone"),
   CONFIG_EDITOR_ACTIVATION_TIMEOUT("iam.config-editor.activation.timeout"),
   CONFIG_EDITOR_VALIDATION_DEFAULT("iam.config-editor.validation.default"),
   CONFIG_EDITOR_PLUGIN_TRACKING_DEFAULT("iam.config-editor.plugin-tracking.default"),
   CONFIG_EDITOR_SHOW_VARIABLES("iam.config-editor.show-variables"),
   LOGINAPP_URL_PATH("iam.loginapp.url.path"),
   LOGINAPP_APPLICATION_LISTENER("iam.loginapp.application.listener"),
   LOGINAPP_CLASSPATH("iam.internal.loginapp.classpath"),
   LOGINAPP_CLASSPATH_EXT("iam.loginapp.classpath.ext"),
   LOGINAPP_LOG4J_CONFIGS("iam.loginapp.log4j.configs"),
   LOGINAPP_LAYOUT_DIRS("iam.loginapp.layout.dirs"),
   LOGINAPP_REST_UI_CUSTOMIZATIONS("iam.loginapp.rest.ui.customizations"),
   LOGINAPP_UI_RESOURCE_SETS("iam.loginapp.ui.resource-sets.dir"),
   LOGINAPP_COOKIES_ALLOWEQUALSINVALUE_ENABLED("iam.loginapp.cookies.allowEqualsInValue.enabled"),
   LOGINAPP_COOKIES_ALLOWHTTPSEPSINV0_ENABLED("iam.loginapp.cookies.allowHttpSepsInV0.enabled"),
   TRANSACTION_APPROVAL_URL_PATH("iam.transaction-approval.url.path"),
   TRANSACTION_APPROVAL_LISTENER("iam.transaction-approval.application.listener"),
   TRANSACTION_APPROVAL_CLASSPATH("iam.internal.transaction-approval.classpath"),
   TRANSACTION_APPROVAL_CLASSPATH_EXT("iam.transaction-approval.classpath.ext"),
   TRANSACTION_APPROVAL_LOG4J_CONFIGS("iam.transaction-approval.log4j.configs"),
   API_POLICY_SERVICE_URL_PATH("iam.api-policy-service.url.path"),
   API_POLICY_SERVICE_LISTENER("iam.api-policy-service.application.listener"),
   API_POLICY_SERVICE_CLASSPATH("iam.internal.api-policy-service.classpath"),
   API_POLICY_SERVICE_CLASSPATH_EXT("iam.api-policy-service.classpath.ext"),
   API_POLICY_SERVICE_LOG4J_CONFIGS("iam.api-policy-service.log4j.configs"),
   SERVICE_CONTAINER_URL_PATH("iam.service-container.url.path"),
   SERVICE_CONTAINER_APPLICATION_LISTENER("iam.service-container.application.listener"),
   SERVICE_CONTAINER_CLASSPATH("iam.internal.service-container.classpath"),
   SERVICE_CONTAINER_CLASSPATH_EXT("iam.service-container.classpath.ext"),
   SERVICE_CONTAINER_LOG4J_CONFIGS("iam.service-container.log4j.configs"),
   SERVICE_CONTAINER_LAYOUT_DIRS("iam.service-container.layout.dirs"),
   SCRIPTABLE_LUA_SOCKET_DIR("iam.scriptable.lua.socket.dir"),
   HEALTH_ADDRESS("iam.health.address"),
   HEALTH_PORT("iam.health.port"),
   METRICS_PORT("iam.metrics.port"),
   H2_URL_PATH("iam.h2.url.path"),
   H2_DATA_DIR("iam.h2.data.dir"),
   H2_JDBC_URL("iam.h2.jdbc.url"),
   H2_JDBC_USER("iam.h2.jdbc.user"),
   H2_JDBC_PASSWORD("iam.h2.jdbc.password"),
   H2_SKIP_ADMIN_PASSWORD_CHANGE("iam.internal.h2.skip-admin-password-change"),
   DOCKER("iam.internal.docker"),
   DISABLE_ANALYTICS_OVERRIDE("iam.analytics.disabled"),
   IAM_ANALYTICS_MODE("iam.analytics.mode");

   private final String systemPropertyKey;
   private final String environmentKey;
   private final String propertyFileKey;
   private final boolean emptyValueAllowed;

   ParameterSpec(String canonicalKey) {
      this(canonicalKey, false);
   }

   ParameterSpec(String canonicalKey, boolean emptyValueAllowed) {
      this.systemPropertyKey = canonicalKey;
      this.environmentKey = toEnvironmentKey(canonicalKey);
      this.propertyFileKey = canonicalKey;
      this.emptyValueAllowed = emptyValueAllowed;
   }

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

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

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

   public boolean isEmptyValueAllowed() {
      return this.emptyValueAllowed;
   }

   public boolean isPublic() {
      return !this.systemPropertyKey.startsWith("iam.internal");
   }

   public boolean isSensitive() {
      return this.systemPropertyKey.contains(".password");
   }

   @Override
   public String toString() {
      return this.propertyFileKey + "/" + this.environmentKey;
   }

   public static ParameterSpec ofPropertyFileKey(String key) {
      return Stream.of(values()).filter(p -> p.propertyFileKey.equals(key)).findFirst().orElseThrow(() -> new NoSuchElementException(key));
   }

   private static String toEnvironmentKey(String canonicalKey) {
      return Pattern.compile("\\W").matcher(canonicalKey).replaceAll("_").toUpperCase(Locale.ROOT);
   }
}
