package com.airlock.iam.common.application.configuration.event;

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.BooleanProperty;
import com.airlock.iam.plugin.api.annotation.property.RegexProperty;
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.PropertyConfigurationException;
import com.airlock.iam.plugin.api.valuereader.BooleanPropertyValueReader;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.regex.Pattern;

@Plugin(
   description = "Event that is published when user roles are changed in the Adminapp.<p>The event data contains the string lists <tt>event.data.oldRoles</tt> and <tt>event.data.newRoles</tt> (all the user's roles after the change), as well as (for convenience) <tt>event.data.addedRoles</tt> and <tt>event.data.removedRoles</tt>.</p>",
   displayName = "User Roles Changed"
)
public final class UserRolesChangedSubscribedEventConfig implements AdminappUserSubscribedEventConfig {
   @RegexProperty(
      description = "A pattern for matching the changed roles. The event is only handled if at least one of the changed roles (added or removed) matches the pattern.",
      optional = true,
      defaultValue = ".*",
      exampleValues = {".*", ".*-admin", "employee"}
   )
   private Pattern rolePattern;
   @BooleanProperty(
      description = "If enabled, events that involve at least one added role (matching the pattern above) will be handled.",
      optional = true,
      defaultValue = "true"
   )
   private boolean handleAddedRoles;
   private static final String HANDLE_ADDED_ROLES_FIELD = "handleAddedRoles";
   @BooleanProperty(
      description = "If enabled, events that involve at least one removed role (matching the pattern above) will be handled.",
      optional = true,
      defaultValue = "true"
   )
   private boolean handleRemovedRoles;
   private static final String HANDLE_REMOVED_ROLES_FIELD = "handleRemovedRoles";

   @ConfigurationValidator
   public static void validateFilter(PluginConfiguration config, ConfigurationEnvironment env, ConfigurationContext context, Environment valenv) throws ConfigurationException {
      boolean added = BooleanPropertyValueReader.effectiveBooleanPropertyValue(config, "handleAddedRoles", env, context);
      boolean removed = BooleanPropertyValueReader.effectiveBooleanPropertyValue(config, "handleRemovedRoles", env, context);
      if (!added && !removed) {
         throw new PropertyConfigurationException(
            config,
            env,
            context,
            "At least one of \"Handle Added Roles\" or \"Handle Removed Roles\" must be enabled.",
            new String[]{"handleAddedRoles", "handleRemovedRoles"}
         );
      }
   }

   public Pattern getRolePattern() {
      return this.rolePattern;
   }

   public boolean isHandleAddedRoles() {
      return this.handleAddedRoles;
   }

   public boolean isHandleRemovedRoles() {
      return this.handleRemovedRoles;
   }

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

   @SuppressFBWarnings(justification = "generated code")
   public UserRolesChangedSubscribedEventConfig(Pattern rolePattern, boolean handleAddedRoles, boolean handleRemovedRoles) {
      this.rolePattern = rolePattern;
      this.handleAddedRoles = handleAddedRoles;
      this.handleRemovedRoles = handleRemovedRoles;
   }

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

   @SuppressFBWarnings(justification = "generated code")
   public static class UserRolesChangedSubscribedEventConfigBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private Pattern rolePattern;
      @SuppressFBWarnings(justification = "generated code")
      private boolean handleAddedRoles;
      @SuppressFBWarnings(justification = "generated code")
      private boolean handleRemovedRoles;

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

      @SuppressFBWarnings(justification = "generated code")
      public UserRolesChangedSubscribedEventConfig.UserRolesChangedSubscribedEventConfigBuilder rolePattern(Pattern rolePattern) {
         this.rolePattern = rolePattern;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public UserRolesChangedSubscribedEventConfig.UserRolesChangedSubscribedEventConfigBuilder handleAddedRoles(boolean handleAddedRoles) {
         this.handleAddedRoles = handleAddedRoles;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public UserRolesChangedSubscribedEventConfig.UserRolesChangedSubscribedEventConfigBuilder handleRemovedRoles(boolean handleRemovedRoles) {
         this.handleRemovedRoles = handleRemovedRoles;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public UserRolesChangedSubscribedEventConfig build() {
         return new UserRolesChangedSubscribedEventConfig(this.rolePattern, this.handleAddedRoles, this.handleRemovedRoles);
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "UserRolesChangedSubscribedEventConfig.UserRolesChangedSubscribedEventConfigBuilder(rolePattern="
            + this.rolePattern
            + ", handleAddedRoles="
            + this.handleAddedRoles
            + ", handleRemovedRoles="
            + this.handleRemovedRoles
            + ")";
      }
   }
}
