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

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.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 = "Information item to be requested from the holder and verified.", displayName = "SSI Claim")
public final class SsiClaimConfig {
   @StringProperty(
      description = "Credential schema name for this claim. Restricts the claim settings (trusted issuers & requested attributes) to this schema.",
      exampleValues = "Person with Age Check",
      optional = false
   )
   private String credentialSchemaName;
   @StringListProperty(
      description = "Restricts credential to these issuer DIDs. If left empty, a credential is accepted from any issuer.",
      exampleElements = "did:web:core.trial.procivis-one.com:ssi:did-web:v1:7cf45c31-831f-4210-b413-d3866145ded9",
      minElements = 1,
      unique = true,
      optional = true
   )
   private List<String> trustedIssuers;
   @PluginListProperty(
      description = "Attributes to request from a user. These attributes must also exist in the corresponding proof schema.\nAll requested attributes must be shared by the user, otherwise the step fails.",
      minElements = 1,
      optional = false
   )
   private List<SsiAttributeConfig> requestedAttributes;

   public SsiClaimConfig(String credentialSchemaName, List<String> trustedIssuers, List<SsiAttributeConfig> requestedAttributes) {
      this.trustedIssuers = trustedIssuers;
      this.requestedAttributes = requestedAttributes;
      this.credentialSchemaName = credentialSchemaName;
   }

   public String getCredentialSchemaName() {
      return this.credentialSchemaName;
   }

   public List<String> getTrustedIssuers() {
      return this.trustedIssuers;
   }

   public List<SsiAttributeConfig> getRequestedAttributes() {
      return this.requestedAttributes;
   }

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

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

   @SuppressFBWarnings(justification = "generated code")
   public static class SsiClaimConfigBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private String credentialSchemaName;
      @SuppressFBWarnings(justification = "generated code")
      private ArrayList<String> trustedIssuers;
      @SuppressFBWarnings(justification = "generated code")
      private ArrayList<SsiAttributeConfig> requestedAttributes;

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

      @SuppressFBWarnings(justification = "generated code")
      public SsiClaimConfig.SsiClaimConfigBuilder credentialSchemaName(String credentialSchemaName) {
         this.credentialSchemaName = credentialSchemaName;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public SsiClaimConfig.SsiClaimConfigBuilder trustedIssuer(String trustedIssuer) {
         if (this.trustedIssuers == null) {
            this.trustedIssuers = new ArrayList<>();
         }

         this.trustedIssuers.add(trustedIssuer);
         return this;
      }

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

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

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

      @SuppressFBWarnings(justification = "generated code")
      public SsiClaimConfig.SsiClaimConfigBuilder clearTrustedIssuers() {
         if (this.trustedIssuers != null) {
            this.trustedIssuers.clear();
         }

         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public SsiClaimConfig.SsiClaimConfigBuilder requestedAttribute(SsiAttributeConfig requestedAttribute) {
         if (this.requestedAttributes == null) {
            this.requestedAttributes = new ArrayList<>();
         }

         this.requestedAttributes.add(requestedAttribute);
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public SsiClaimConfig.SsiClaimConfigBuilder requestedAttributes(Collection<? extends SsiAttributeConfig> requestedAttributes) {
         if (requestedAttributes == null) {
            throw new NullPointerException("requestedAttributes cannot be null");
         }

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

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

      @SuppressFBWarnings(justification = "generated code")
      public SsiClaimConfig.SsiClaimConfigBuilder clearRequestedAttributes() {
         if (this.requestedAttributes != null) {
            this.requestedAttributes.clear();
         }

         return this;
      }

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

         return new SsiClaimConfig(this.credentialSchemaName, trustedIssuers, switch (this.requestedAttributes == null ? 0 : this.requestedAttributes.size()) {
            case 0 -> Collections.emptyList();
            case 1 -> Collections.singletonList(this.requestedAttributes.get(0));
            default -> Collections.unmodifiableList(new ArrayList<>(this.requestedAttributes));
         });
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "SsiClaimConfig.SsiClaimConfigBuilder(credentialSchemaName="
            + this.credentialSchemaName
            + ", trustedIssuers="
            + this.trustedIssuers
            + ", requestedAttributes="
            + this.requestedAttributes
            + ")";
      }
   }
}
