package com.airlock.iam.flow.shared.application.configuration.valueprovider;

import com.airlock.iam.common.api.application.configuration.encoder.StringEncoderConfig;
import com.airlock.iam.common.application.configuration.event.EventReadyValueMapProviderConfig;
import com.airlock.iam.flow.api.application.configuration.valueprovider.ValueMapProviderConfig;
import com.airlock.iam.plugin.api.annotation.config.Plugin;
import com.airlock.iam.plugin.api.annotation.property.PluginListProperty;
import com.airlock.iam.plugin.api.annotation.property.StringProperty;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

@Plugin(
   description = "Value map provider of a list of roles or a single separator concatenated string. Note that not all consumers of these values can handle values of type \"list of string\", in particular it doesn't work with string formatting. <p>The following values are provided: <ul><li><b>roles</b>: a string with the concatenated roles (including timeout and lifetime if present).</li><li><b>roles-list</b>: the roles as a list (including timeout and lifetime if present).</li><li><b>role-names</b>: a string with the concatenated role names (without timeout and lifetime).</li><li><b>role-names-list</b>: the role names as a list (without timeout and lifetime).</li></ul></p>"
)
public class RolesProviderConfig implements ValueMapProviderConfig, EventReadyValueMapProviderConfig {
   public static final String ROLES_KEY = "roles";
   public static final String ROLES_LIST_KEY = "roles-list";
   public static final String ROLE_NAMES_KEY = "role-names";
   public static final String ROLE_NAMES_LIST_KEY = "role-names-list";
   @PluginListProperty(description = "The roles provided by these providers are combined into one string by this plugin.", optional = true)
   private List<RoleProviderConfig> roleProviders;
   @StringProperty(description = "Separator between the roles.", optional = true, defaultValue = ",")
   private String separator;
   @PluginListProperty(description = "Encodes the roles before concatenating them.", optional = true)
   private List<StringEncoderConfig> encoders;

   public String getSeparator() {
      return this.separator;
   }

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

   @SuppressFBWarnings(justification = "generated code")
   public RolesProviderConfig(List<RoleProviderConfig> roleProviders, String separator, List<StringEncoderConfig> encoders) {
      this.roleProviders = roleProviders;
      this.separator = separator;
      this.encoders = encoders;
   }

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

   @SuppressFBWarnings(justification = "generated code")
   public static class RolesProviderConfigBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private ArrayList<RoleProviderConfig> roleProviders;
      @SuppressFBWarnings(justification = "generated code")
      private String separator;
      @SuppressFBWarnings(justification = "generated code")
      private ArrayList<StringEncoderConfig> encoders;

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

      @SuppressFBWarnings(justification = "generated code")
      public RolesProviderConfig.RolesProviderConfigBuilder roleProvider(RoleProviderConfig roleProvider) {
         if (this.roleProviders == null) {
            this.roleProviders = new ArrayList<>();
         }

         this.roleProviders.add(roleProvider);
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public RolesProviderConfig.RolesProviderConfigBuilder roleProviders(Collection<? extends RoleProviderConfig> roleProviders) {
         if (roleProviders == null) {
            throw new NullPointerException("roleProviders cannot be null");
         }

         if (this.roleProviders == null) {
            this.roleProviders = new ArrayList<>();
         }

         this.roleProviders.addAll(roleProviders);
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public RolesProviderConfig.RolesProviderConfigBuilder clearRoleProviders() {
         if (this.roleProviders != null) {
            this.roleProviders.clear();
         }

         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public RolesProviderConfig.RolesProviderConfigBuilder separator(String separator) {
         this.separator = separator;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public RolesProviderConfig.RolesProviderConfigBuilder encoder(StringEncoderConfig encoder) {
         if (this.encoders == null) {
            this.encoders = new ArrayList<>();
         }

         this.encoders.add(encoder);
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public RolesProviderConfig.RolesProviderConfigBuilder encoders(Collection<? extends StringEncoderConfig> encoders) {
         if (encoders == null) {
            throw new NullPointerException("encoders cannot be null");
         }

         if (this.encoders == null) {
            this.encoders = new ArrayList<>();
         }

         this.encoders.addAll(encoders);
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public RolesProviderConfig.RolesProviderConfigBuilder clearEncoders() {
         if (this.encoders != null) {
            this.encoders.clear();
         }

         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public RolesProviderConfig build() {
         List roleProviders = switch (this.roleProviders == null ? 0 : this.roleProviders.size()) {
            case 0 -> Collections.emptyList();
            case 1 -> Collections.singletonList(this.roleProviders.get(0));
            default -> Collections.unmodifiableList(new ArrayList<>(this.roleProviders));
         };

         return new RolesProviderConfig(roleProviders, this.separator, switch (this.encoders == null ? 0 : this.encoders.size()) {
            case 0 -> Collections.emptyList();
            case 1 -> Collections.singletonList(this.encoders.get(0));
            default -> Collections.unmodifiableList(new ArrayList<>(this.encoders));
         });
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "RolesProviderConfig.RolesProviderConfigBuilder(roleProviders="
            + this.roleProviders
            + ", separator="
            + this.separator
            + ", encoders="
            + this.encoders
            + ")";
      }
   }
}
