package com.airlock.iam.admin.application.configuration.users;

import com.airlock.iam.common.api.domain.model.role.Role;
import com.airlock.iam.elog.api.ELogger;
import com.airlock.iam.elog.api.ELoggerFactory;
import com.google.common.base.Preconditions;
import java.util.List;
import java.util.Optional;
import java.util.Set;

public class RoleSpecificConfigSelector {
   private static final ELogger LOG = ELoggerFactory.getLogger(RoleSpecificConfigSelector.class);
   private final List<AdminRoleSpecificSetting> adminRoleSpecificSettings;
   private final UserRepositoryConfiguration defaultUserRepositoryConfig;
   private final List<String> defaultAvailableUserRoles;
   private final RolebasedConfigSelectionStrategy selectionStratetgy;

   RoleSpecificConfigSelector(
      List<AdminRoleSpecificSetting> adminRoleSpecificSettings,
      UserRepositoryConfiguration defaultUserRepositoryConfig,
      List<String> defaultAvailableUserRoles,
      RolebasedConfigSelectionStrategy selectionStratetgy
   ) {
      this.adminRoleSpecificSettings = (List<AdminRoleSpecificSetting>)Preconditions.checkNotNull(adminRoleSpecificSettings);
      this.defaultUserRepositoryConfig = (UserRepositoryConfiguration)Preconditions.checkNotNull(defaultUserRepositoryConfig);
      this.defaultAvailableUserRoles = defaultAvailableUserRoles;
      this.selectionStratetgy = selectionStratetgy;
   }

   public UserRepositoryConfiguration getUserRepositorySettings(Set<Role> adminRoles) {
      Optional<AdminRoleSpecificSetting> specificSetting = this.findSpecificSettings(adminRoles);
      if (specificSetting.isPresent() && specificSetting.get().getUserRepositoryConfiguration().isPresent()) {
         LOG.debug("Selected specific user store requiring admin roles: " + specificSetting.get().getRequiredAdminRoles());
         return specificSetting.get().getUserRepositoryConfiguration().get();
      } else {
         return this.defaultUserRepositoryConfig;
      }
   }

   public List<String> getAvailableUserRoles(Set<Role> adminRoles) {
      Optional<AdminRoleSpecificSetting> specificSetting = this.findSpecificSettings(adminRoles);
      if (specificSetting.isPresent() && !specificSetting.get().getAvailableUserRoles().isEmpty()) {
         LOG.debug("Selected specific user roles requiring admin roles: " + specificSetting.get().getRequiredAdminRoles());
         return specificSetting.get().getAvailableUserRoles();
      } else {
         return this.defaultAvailableUserRoles;
      }
   }

   private Optional<AdminRoleSpecificSetting> findSpecificSettings(Set<Role> adminRoles) {
      return this.adminRoleSpecificSettings
         .stream()
         .filter(setting -> !adminRoles.isEmpty())
         .filter(settings -> this.selectionStratetgy.isConfigApplicapleForAdminWithRoles(settings, adminRoles))
         .findFirst();
   }
}
