package com.airlock.iam.admin.application.service.access;

import com.airlock.iam.common.api.domain.model.authentication.Authentee;
import com.airlock.iam.common.api.domain.model.role.Role;
import com.airlock.iam.core.misc.authorization.AccessController;
import com.airlock.iam.elog.api.ELogger;
import com.airlock.iam.elog.api.ELoggerFactory;
import com.google.common.base.Splitter;
import com.google.common.collect.Sets;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class ActionBasedAccessController implements AccessController {
   private static final ELogger LOG = ELoggerFactory.getLogger(ActionBasedAccessController.class);
   private static final String NO_RESTRICTION = "NO RESTRICTION";
   private final Map<String, Set<String>> actions = new HashMap<>();

   public boolean isActionDefined(String action) {
      return this.actions.containsKey(action);
   }

   public boolean isActionAllowedFor(String action, Authentee subject) {
      if (subject != null && action != null && this.isActionDefined(action)) {
         Set<String> requiredRoles = this.actions.get(action);
         if (requiredRoles.size() == 1) {
            String singleRole = requiredRoles.iterator().next();
            if ("NO RESTRICTION".equals(singleRole)) {
               LOG.debug("Accepting " + action + " because it's configured with 'NO RESTRICTION'.");
               return true;
            }
         }

         for (Role role : subject.roles()) {
            if (requiredRoles.contains(role.getRoleName())) {
               return true;
            }
         }

         LOG.debug("Denying " + action + " because user '" + subject.userIdentity().id() + "' has none of roles " + requiredRoles);
         return false;
      } else {
         return false;
      }
   }

   public void addAction(String name, String roles) {
      Set<String> roleSet = Sets.newHashSet(Splitter.on(',').trimResults().split(roles));
      this.actions.put(name, roleSet);
   }
}
