package de.ivu.elect.presentation.wahl;

import java.io.Serializable;
import java.util.Objects;
import java.util.Set;

import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;

import de.ivu.elect.business.gebietsbaum.boundary.GebietExtendedDAO;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.mandant.entity.Mandant;
import de.ivu.elect.business.wahl.boundary.WahlExtendedDAO;
import de.ivu.elect.business.wahl.entity.Wahl;

@RequestScoped
public class WahlMandantenAufteilenPermissions implements Serializable {

  private static final long serialVersionUID = 1L;

  @Inject
  private transient WahlExtendedDAO wahlExtendedDAO;

  @Inject
  private transient GebietExtendedDAO gebietExtendedDAO;

  public boolean isGebietAnlegenMoeglich(Gebiet gebiet) {
    return gebiet == null || gebiet.getWahl() == null || (gebiet.getWahl()
        .getBerichtetAn() == null /*ELECT-8023 Gebiete nur anlegbar, wenn Wahl nicht an andere Wahl berichtet*/ && !isWahlAufgeteiltGebietOderDrueber(gebiet));
  }

  public boolean isGebietLoeschenMoeglich(Gebiet gebiet) {
    return gebiet == null || gebiet.getWahl() == null || gebiet.getGebietsart().isStimmbezirk() || gebiet.getGebietsart().isBriefwahlbezirk() /*Stimmbezirke/Briefwahlbezirke immer löschbar*/ ||
        (gebiet.getWahl().getBerichtetAn() == null /*ELECT-8023 Gebiete nur löschbar, wenn Wahl nicht an andere Wahl berichtet*/ && !isWahlAufgeteiltGebietOderDrueber(gebiet) && !isWahlAufgeteiltGebietOderDrunter(gebiet));
  }

  private boolean isWahlAufgeteiltGebietOderDrueber(Gebiet gebiet) {
    Set<Mandant> verantwortlicheMandantenAbgeleitet = gebiet.getVerantwortlicheMandantenAbgeleitet();

    if (verantwortlicheMandantenAbgeleitet.isEmpty()) {
      return false;
    }

    Wahl wahl = gebiet.getWahl();
    if (wahl==null) {
      return false;
    }
    return verantwortlicheMandantenAbgeleitet.stream()
        .anyMatch(verantwortlicherMandantAbgeleitet -> !wahlExtendedDAO.findByBerichtetAnAndMandant(wahl, verantwortlicherMandantAbgeleitet).isEmpty());
  }

  private boolean isWahlAufgeteiltGebietOderDrunter(Gebiet gebiet) {
    Wahl wahl = gebiet.getWahl();
    if (wahl==null){
      return false;
    }

    return gebietExtendedDAO.findByWahlMitVerantwortlicherMandant(wahl).stream()
        .filter(gebietUnterhalb -> gebietUnterhalb.isUntergebietVon(gebiet))
        .map(Gebiet::getVerantwortlicherMandant).filter(Objects::nonNull)
        .anyMatch(verantwortlicherMandant -> !wahlExtendedDAO.findByBerichtetAnAndMandant(wahl, verantwortlicherMandant).isEmpty());
  }



}
