package com.airlock.iam.common.domain.model.claims;

import com.airlock.iam.base.api.domain.model.exception.FailureException;
import com.airlock.iam.common.api.domain.model.claims.Claim;
import com.airlock.iam.common.api.domain.model.claims.ClaimValue;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;

public final class ClaimSet implements ClaimValue {
   private final Collection<Claim<?>> claims;

   public static ClaimSet claimSet(Collection<Claim<?>> claims) {
      verifyUniqueClaims(claims);
      return new ClaimSet(claims);
   }

   public static Collection<Claim<?>> verifyUniqueClaims(Collection<Claim<?>> claims) {
      Set<String> seenClaimNames = new HashSet<>();

      for (Claim<?> claim : claims) {
         if (seenClaimNames.contains(claim.name())) {
            throw new FailureException(String.format("Invalid claim set: found duplicate claim \"%s\"", claim.name()));
         }

         seenClaimNames.add(claim.name());
      }

      return claims;
   }

   @Override
   public Object toJSONSerializable() {
      return this.claims.stream().collect(Collectors.toMap(Claim::name, claim -> claim.value().toJSONSerializable()));
   }

   @SuppressFBWarnings(justification = "generated code")
   private ClaimSet(Collection<Claim<?>> claims) {
      this.claims = claims;
   }

   @SuppressFBWarnings(justification = "generated code")
   public Collection<Claim<?>> getClaims() {
      return this.claims;
   }
}
