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 any claims that are requested using scope values from the UserInfo Endpoint. If no UserInfo claims are configured, the claims being requested from the UserInfo Endpoint are only those requested using scope values.",
   displayName = "UserInfo Claim"
)
public class UserInfoClaimConfig implements ClaimRequestConfig {
   @StringProperty(
      description = "The claim to request to be returned from the UserInfo Endpoint.",
      exampleValues = {"given_name", "nickname", "email", "email_verified"},
      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.USERINFO;
   }

   @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 UserInfoClaimConfig.UserInfoClaimConfigBuilder builder() {
      return new UserInfoClaimConfig.UserInfoClaimConfigBuilder();
   }

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

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

   @SuppressFBWarnings(justification = "generated code")
   public static class UserInfoClaimConfigBuilder {
      @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")
      UserInfoClaimConfigBuilder() {
      }

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

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

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

      @SuppressFBWarnings(justification = "generated code")
      public UserInfoClaimConfig.UserInfoClaimConfigBuilder 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 UserInfoClaimConfig.UserInfoClaimConfigBuilder clearValues() {
         if (this.values != null) {
            this.values.clear();
         }

         return this;
      }

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

      @SuppressFBWarnings(justification = "generated code")
      public UserInfoClaimConfig build() {
         return new UserInfoClaimConfig(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 "UserInfoClaimConfig.UserInfoClaimConfigBuilder(claim=" + this.claim + ", values=" + this.values + ", requirement=" + this.requirement + ")";
      }
   }
}
