package com.airlock.iam.authentication.domain.model.risk.accesspolicy;

import com.airlock.iam.authentication.application.configuration.risk.RiskTagPlugin;
import com.airlock.iam.authentication.application.configuration.risk.accesspolicy.SimpleRiskBasedRoleDerivationConfig;
import com.airlock.iam.authentication.domain.model.risk.RiskTagImpl;
import com.airlock.iam.authentication.domain.model.risk.RiskTags;
import com.google.common.collect.Sets;
import java.util.Set;

public class SimpleRiskBasedRoleDerivation implements RoleDerivationRule {
   private final SimpleRiskBasedRoleDerivationConfig config;

   public SimpleRiskBasedRoleDerivation(SimpleRiskBasedRoleDerivationConfig riskBasedRoleDerivationConfig) {
      this.config = riskBasedRoleDerivationConfig;
   }

   @Override
   public Set<String> getDerivedRoles(String username, Set<String> grantedRoles, Set<String> derivedRoles, RiskTags riskTags) {
      if (!this.satisfiesRoleConditions(grantedRoles, derivedRoles)) {
         return Sets.newHashSet();
      } else {
         return !this.satisfiesRiskTagConditions(riskTags) ? Sets.newHashSet() : Sets.newHashSet(new String[]{this.config.getTargetRole()});
      }
   }

   private boolean satisfiesRiskTagConditions(RiskTags riskTags) {
      for (RiskTagPlugin mandatoryRiskTag : this.config.getMandatoryRiskTags()) {
         if (!riskTags.containsRiskTag(RiskTagImpl.of(mandatoryRiskTag.getName()))) {
            return false;
         }
      }

      for (RiskTagPlugin excludingRiskTag : this.config.getExcludingRiskTags()) {
         if (riskTags.containsRiskTag(RiskTagImpl.of(excludingRiskTag.getName()))) {
            return false;
         }
      }

      return true;
   }

   private boolean satisfiesRoleConditions(Set<String> grantedRoles, Set<String> derivedRoles) {
      if (this.config.getRequiredRoles().isEmpty()) {
         return true;
      }

      for (String role : this.config.getRequiredRoles()) {
         if (grantedRoles.contains(role) || derivedRoles.contains(role)) {
            return true;
         }
      }

      return false;
   }
}
