package com.airlock.iam.login.application.configuration.targetapp;

import com.airlock.iam.plugin.api.annotation.config.ConfigurationValidator;
import com.airlock.iam.plugin.api.annotation.config.Plugin;
import com.airlock.iam.plugin.api.annotation.property.IntegerProperty;
import com.airlock.iam.plugin.api.config.ConfigurationContext;
import com.airlock.iam.plugin.api.config.ConfigurationEnvironment;
import com.airlock.iam.plugin.api.config.Environment;
import com.airlock.iam.plugin.api.config.PluginConfiguration;
import com.airlock.iam.plugin.api.exception.ConfigurationException;
import com.airlock.iam.plugin.api.exception.PropertyConstraintViolationException;
import com.airlock.iam.plugin.api.valuereader.IntegerPropertyValueReader;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;

@Plugin(
   description = "<p>Static timeouts, which are always applied. Use 0 to apply the default Airlock Gateway idle timeout or lifetime.</p><p><ul><li>If both values are set, \"Idle Timeout\" has to be smaller or equal to \"Lifetime\".</li><li>Either \"Idle Timeout\" or \"Lifetime\" has to be set. If only one is set, the other value is implicitly treated as 0 and the default Airlock Gateway timeout is used.</li></ul></p>"
)
public class StaticTimeoutProviderConfig implements TimeoutProviderConfig {
   @IntegerProperty(
      description = "Idle timeout in seconds. The Airlock Gateway default idle timeout is used when the value is not set or set to 0. Either \"Idle Timeout\" or \"Lifetime\" has to be set. If only one is set, the other value is implicitly treated as 0 and the default Airlock Gateway timeout is used.",
      exampleValues = {60, 300, 1800},
      optional = true,
      displayName = "Idle Timeout [s]",
      mandatoryUnless = "lifetime",
      minValue = 0
   )
   private Integer idleTimeout;
   private static final String IDLE_TIMEOUT_FIELD = "idleTimeout";
   public static final String IDLE_TIMEOUT_DISPLAY_NAME = "Idle Timeout";
   @IntegerProperty(
      description = "Lifetime in seconds. The Airlock Gateway default lifetime is used when the value is is not set or set to 0. Either \"Idle Timeout\" or \"Lifetime\" has to be set. If only one is set, the other value is implicitly treated as 0 and the default Airlock Gateway timeout is used.",
      exampleValues = {600, 1800, 7200},
      optional = true,
      displayName = "Lifetime [s]",
      mandatoryUnless = "idleTimeout",
      minValue = 0
   )
   private Integer lifetime;
   private static final String LIFETIME_FIELD = "lifetime";
   public static final String LIFETIME_DISPLAY_NAME = "Lifetime";

   @ConfigurationValidator
   static void checkProperties(PluginConfiguration config, ConfigurationEnvironment env, ConfigurationContext context, Environment validationEnvironment) throws ConfigurationException {
      Integer configuredIdleTimeout = IntegerPropertyValueReader.effectiveIntegerConfigValue(config, "idleTimeout", env, context);
      Integer configuredLifeTime = IntegerPropertyValueReader.effectiveIntegerConfigValue(config, "lifetime", env, context);
      if (configuredLifeTime != null
         && configuredIdleTimeout != null
         && configuredLifeTime != 0
         && configuredIdleTimeout != 0
         && configuredLifeTime < configuredIdleTimeout) {
         throw new PropertyConstraintViolationException(
            "lifetime", config, env, context, "The \"Lifetime\" should be equal or greater than the \"Idle Timeout\"."
         );
      }
   }

   public Integer getIdleTimeout() {
      return this.idleTimeout;
   }

   public Integer getLifetime() {
      return this.lifetime;
   }

   @SuppressFBWarnings(justification = "generated code")
   public static StaticTimeoutProviderConfig.StaticTimeoutProviderConfigBuilder builder() {
      return new StaticTimeoutProviderConfig.StaticTimeoutProviderConfigBuilder();
   }

   @SuppressFBWarnings(justification = "generated code")
   public StaticTimeoutProviderConfig(Integer idleTimeout, Integer lifetime) {
      this.idleTimeout = idleTimeout;
      this.lifetime = lifetime;
   }

   @SuppressFBWarnings(justification = "generated code")
   public StaticTimeoutProviderConfig() {
   }

   @SuppressFBWarnings(justification = "generated code")
   public static class StaticTimeoutProviderConfigBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private Integer idleTimeout;
      @SuppressFBWarnings(justification = "generated code")
      private Integer lifetime;

      @SuppressFBWarnings(justification = "generated code")
      StaticTimeoutProviderConfigBuilder() {
      }

      @SuppressFBWarnings(justification = "generated code")
      public StaticTimeoutProviderConfig.StaticTimeoutProviderConfigBuilder idleTimeout(Integer idleTimeout) {
         this.idleTimeout = idleTimeout;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public StaticTimeoutProviderConfig.StaticTimeoutProviderConfigBuilder lifetime(Integer lifetime) {
         this.lifetime = lifetime;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public StaticTimeoutProviderConfig build() {
         return new StaticTimeoutProviderConfig(this.idleTimeout, this.lifetime);
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "StaticTimeoutProviderConfig.StaticTimeoutProviderConfigBuilder(idleTimeout=" + this.idleTimeout + ", lifetime=" + this.lifetime + ")";
      }
   }
}
