package com.airlock.iam.servicecontainer.app.application.configuration.radius;

import com.airlock.iam.core.misc.authen.Authentee;
import com.airlock.iam.plugin.api.annotation.property.PluginListProperty;
import com.airlock.iam.plugin.api.annotation.property.StringListProperty;
import com.airlock.iam.servicecontainer.app.application.configuration.RoleTransformationRuleConfig;
import com.airlock.iam.servicecontainer.app.application.service.radius.wrapper.lib.IamRadiusServerAccessRequest;
import com.google.common.collect.Lists;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.net.InetAddress;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

public abstract class TargetServiceConfig {
   @StringListProperty(
      description = "A list of roles used to access the target service.<p>The user needs <b>one of the roles</b> in order to get access to the target service.</p><p>If no roles are configured, <b>all authenticated users may access the target service</b>.</p><p>The roles may be transformed before being compared to this list using the role transformers (see separate property).</p>",
      optional = true,
      exampleElements = {"user", "admin", "employee"}
   )
   private List<String> requiredRoles = Lists.newArrayList();
   @PluginListProperty(
      description = "A list of transformation rules used to modify user roles before being compared to the roles required by an application.",
      optional = true
   )
   private List<RoleTransformationRuleConfig> roleTransformationRules = Lists.newArrayList();

   private String transformRole(String role) {
      String r = role;

      for (RoleTransformationRuleConfig rule : this.roleTransformationRules) {
         r = rule.transformRole(r);
      }

      return r;
   }

   public abstract boolean matches(IamRadiusServerAccessRequest var1, InetAddress var2);

   public final List<String> getRequiredRoles() {
      return List.copyOf(this.requiredRoles);
   }

   public final boolean mayUserAccessService(Authentee user) {
      Objects.requireNonNull(user, "user null");
      if (this.requiredRoles.isEmpty()) {
         return true;
      }

      String[] userRoles = user.getGrantedRoleNames();
      return userRoles == null ? false : Arrays.stream(userRoles).map(this::transformRole).anyMatch(this.requiredRoles::contains);
   }

   @SuppressFBWarnings(justification = "generated code")
   public TargetServiceConfig(List<String> requiredRoles, List<RoleTransformationRuleConfig> roleTransformationRules) {
      this.requiredRoles = requiredRoles;
      this.roleTransformationRules = roleTransformationRules;
   }

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