package com.airlock.iam.oauth2.application.configuration;

import com.airlock.iam.plugin.api.annotation.config.Plugin;
import com.airlock.iam.plugin.api.annotation.property.EnumProperty;
import com.airlock.iam.plugin.api.annotation.property.StringListProperty;
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 = "The configured claim is requested to be added to the default claims in the ID Token returned from the authorization server. <p>Note that the authorization server may not support requesting the configured claim (or requesting claims at all).</p>",
   displayName = "ID Token Claim"
)
public class IdTokenClaimConfig implements ClaimRequestConfig {
   @StringProperty(description = "The claim to request to be included in the ID Token.", exampleValues = {"sub", "acr", "auth_time"}, optional = false)
   private String claim;
   public static final String CLAIM_FIELD = "claim";
   @StringListProperty(
      description = "Requests that the claim be returned with a particular value. The value must be a valid value for the claim being requested. <p>If multiple values are configured, the request indicates that the claim should be returned with one of the given values. The values in the request appear in order of preference.</p>If not configured, the claim is requested without a restriction on its value.",
      optional = true,
      minElements = 1,
      unique = true,
      exampleElements = {"urn:mace:incommon:iap:silver", "sub248289761001"}
   )
   private List<String> values;
   @EnumProperty(
      description = "The client indicates whether the claim being requested is an essential or a voluntary claim.<ul><li>Essential: the claim is necessary to ensure a smooth authorization experience for the specific task requested by the end-user.</li><li>Voluntary: the claim is useful but not essential for the specific task requested by the end-user</li></ul><b>Note</b> that even if a claim is requested as 'essential', the authorization server is not obligated to return it.",
      defaultValue = "ESSENTIAL",
      optional = true
   )
   private ClaimRequestRequirement requirement;

   @Override
   public ClaimRequestMember getTopLevelMember() {
      return ClaimRequestMember.ID_TOKEN;
   }

   @Override
   public String getClaim() {
      return this.claim;
   }

   @Override
   public List<String> getValues() {
      return this.values;
   }

   @Override
   public ClaimRequestRequirement getRequirement() {
      return this.requirement;
   }

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

   @SuppressFBWarnings(justification = "generated code")
   public IdTokenClaimConfig(String claim, List<String> values, ClaimRequestRequirement requirement) {
      this.claim = claim;
      this.values = values;
      this.requirement = requirement;
   }

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

   @SuppressFBWarnings(justification = "generated code")
   public static class IdTokenClaimConfigBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private String claim;
      @SuppressFBWarnings(justification = "generated code")
      private ArrayList<String> values;
      @SuppressFBWarnings(justification = "generated code")
      private ClaimRequestRequirement requirement;

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

      @SuppressFBWarnings(justification = "generated code")
      public IdTokenClaimConfig.IdTokenClaimConfigBuilder claim(String claim) {
         this.claim = claim;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public IdTokenClaimConfig.IdTokenClaimConfigBuilder value(String value) {
         if (this.values == null) {
            this.values = new ArrayList<>();
         }

         this.values.add(value);
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public IdTokenClaimConfig.IdTokenClaimConfigBuilder values(Collection<? extends String> values) {
         if (values == null) {
            throw new NullPointerException("values cannot be null");
         }

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

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

      @SuppressFBWarnings(justification = "generated code")
      public IdTokenClaimConfig.IdTokenClaimConfigBuilder clearValues() {
         if (this.values != null) {
            this.values.clear();
         }

         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public IdTokenClaimConfig.IdTokenClaimConfigBuilder requirement(ClaimRequestRequirement requirement) {
         this.requirement = requirement;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public IdTokenClaimConfig build() {
         return new IdTokenClaimConfig(this.claim, switch (this.values == null ? 0 : this.values.size()) {
            case 0 -> Collections.emptyList();
            case 1 -> Collections.singletonList(this.values.get(0));
            default -> Collections.unmodifiableList(new ArrayList<>(this.values));
         }, this.requirement);
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "IdTokenClaimConfig.IdTokenClaimConfigBuilder(claim=" + this.claim + ", values=" + this.values + ", requirement=" + this.requirement + ")";
      }
   }
}
