
package de.ivu.elect.business.benutzerverwaltung.boundary;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.stream.Collectors;

import javax.inject.Inject;

import de.ivu.elect.business.CurrentCustomer;
import de.ivu.elect.business.benutzerverwaltung.entity.BenutzerPK;
import de.ivu.elect.business.benutzerverwaltung.entity.Rolle;
import de.ivu.elect.business.mandant.entity.Mandant;
import de.ivu.elect.business.mandant.entity.MandantArt;
import de.ivu.elect.business.mandant.entity.MandantPK;
import de.ivu.elect.business.security.Customer;
import de.ivu.elect.business.security.UseCasePermission;
import de.ivu.elect.business.security.control.AbstractElectUseCasePermissionFilter;
import de.ivu.elect.business.security.control.ElectCommonPrincipal;


import static java.util.Arrays.stream;

public class PermissionService implements Serializable {

  private static final long serialVersionUID = 1L;

  @Inject
  private transient CurrentCustomer currentCustomer;

  public PermissionService() {
    super();
  }

  public List<UseCasePermission> getAvailablePermissionsForCurrentCustomer(MandantArt mandantArt) {
    return getAvailablePermissionsForCustomers(mandantArt, getCurrentCustomers());
  }

  protected List<UseCasePermission> getAvailablePermissionsForCustomers(MandantArt mandantArt, Collection<Customer> customers) {
    List<UseCasePermission> result = stream(UseCasePermission.values()) //
        .filter(u->u.getMandantArt().isAccept(mandantArt))
        .filter(electCommonPermission -> hasAtLeastOneCurrentCustomer(customers, electCommonPermission)) //
        .filter(useCasePermission -> isNoneExcluded(customers, useCasePermission)) //
        .collect(Collectors.toCollection(ArrayList::new));

    result.remove(UseCasePermission.OHNE); // soll nicht manuell zugewiesen werden können (ELECT-1361)

    return result;
  }

  private boolean isNoneExcluded(Collection<Customer> customers, UseCasePermission useCasePermission) {
    return customers.stream().noneMatch(useCasePermission::isCustomerExcluded);
  }

  private boolean hasAtLeastOneCurrentCustomer(Collection<Customer> customers, UseCasePermission useCasePermission) {
    return customers.stream().anyMatch(useCasePermission::hasCustomer);
  }

  private Collection<Customer> getCurrentCustomers() {
    return currentCustomer.getCustomer().getContainedCustomers();
  }

  public static boolean isNotwendigeRechteVorhanden(Collection<UseCasePermission> rechteRolle, Collection<UseCasePermission> rechtePrincipal, AbstractElectUseCasePermissionFilter useCasePermissionFilter, MandantPK mandantPK) {
    return rechtePrincipal.containsAll(filter(rechteRolle, useCasePermissionFilter, mandantPK));
  }

  private static Collection<UseCasePermission> filter(Collection<UseCasePermission> rechteRolle, AbstractElectUseCasePermissionFilter useCasePermissionFilter, MandantPK mandantPK) {
    return rechteRolle.stream().filter(useCasePermission -> useCasePermissionFilter.test(useCasePermission, mandantPK)).collect(Collectors.toSet());
  }

}
