package com.airlock.iam.application.webserver.infrastructure.properties;

import com.airlock.iam.application.parameters.domain.model.ParameterSpec;
import com.airlock.iam.application.parameters.domain.model.SecureStore;
import com.airlock.iam.elog.api.EDefaultLogType;
import com.airlock.iam.elog.api.ELogger;
import com.airlock.iam.elog.api.ELoggerFactory;
import com.google.common.base.CharMatcher;
import java.util.function.BiConsumer;
import java.util.function.UnaryOperator;

public final class JavaxNetSslTrustStoreProperties {
   private static final ELogger LOG = ELoggerFactory.getLogger(JavaxNetSslTrustStoreProperties.class);
   static final String TRUSTSTORE_TYPE_PROPERTY_NAME = "javax.net.ssl.trustStoreType";
   static final String TRUSTSTORE_FILE_PROPERTY_NAME = "javax.net.ssl.trustStore";
   static final String TRUSTSTORE_PASSWORD_PROPERTY_NAME = "javax.net.ssl.trustStorePassword";
   private final SecureStore secureStore;
   private final UnaryOperator<String> previousPropertyValues;

   public JavaxNetSslTrustStoreProperties(SecureStore secureStore, UnaryOperator<String> previousPropertyValues) {
      this.secureStore = secureStore;
      this.previousPropertyValues = previousPropertyValues;
   }

   public void init(BiConsumer<String, String> propertyDestination) {
      String filePath = this.secureStore.file() == null ? null : this.secureStore.file().toString();
      if (filePath != null && !CharMatcher.whitespace().matchesAllOf(filePath)) {
         if (!this.isTruststoreSystemPropertyDefined()) {
            propertyDestination.accept("javax.net.ssl.trustStoreType", this.secureStore.type());
            propertyDestination.accept("javax.net.ssl.trustStore", filePath);
            propertyDestination.accept("javax.net.ssl.trustStorePassword", this.secureStore.password());
         } else {
            LOG.warn(
               EDefaultLogType.GENERIC_LOG_TYPE,
               String.join(
                  System.lineSeparator(),
                  System.lineSeparator(),
                  "**********************************************************************************",
                  "*****               You have configured multiple trust stores                *****",
                  "*****                   in your \"instance.properties\" file                   *****",
                  "**********************************************************************************",
                  quote(ParameterSpec.JAVA_OPTS.systemPropertyKey())
                     + ": "
                     + this.getSystemPropertyValueOfTrustStoreFile()
                     + " (from property "
                     + quote("javax.net.ssl.trustStore")
                     + ")",
                  quote(ParameterSpec.WEB_SERVER_HTTPS_TRUSTSTORE_FILE.systemPropertyKey()) + ": " + filePath,
                  "It is strongly recommended to only use the property " + quote(ParameterSpec.WEB_SERVER_HTTPS_TRUSTSTORE_FILE.systemPropertyKey()) + "!",
                  "The manually defined system property " + quote("javax.net.ssl.trustStore") + " will be used instead of",
                  quote(ParameterSpec.WEB_SERVER_HTTPS_TRUSTSTORE_FILE.systemPropertyKey()) + " by some legacy or custom plugins.",
                  System.lineSeparator()
               )
            );
         }
      }
   }

   private boolean isTruststoreSystemPropertyDefined() {
      return this.getSystemPropertyValueOfTrustStoreFile() != null;
   }

   private String getSystemPropertyValueOfTrustStoreFile() {
      return this.previousPropertyValues.apply("javax.net.ssl.trustStore");
   }

   private static String quote(String unquoted) {
      return unquoted == null ? "[null]" : "\"" + unquoted + "\"";
   }
}
