
package de.ivu.elect.business.gruppeimgebiet.control;

import de.ivu.elect.business.gebietsbaum.boundary.GebietDAO;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.gebietsbaum.entity.GebietTK;
import de.ivu.elect.business.gruppe.boundary.GruppeDAO;
import de.ivu.elect.business.gruppe.entity.Gruppe;
import de.ivu.elect.business.gruppe.entity.GruppeTK;
import de.ivu.elect.business.gruppeimgebiet.entity.GruppeImGebiet;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.jee.exchange.Violations;

import javax.inject.Inject;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;

public class GruppeImGebietGruppenGebieteValidator {

  @Inject
  private transient GebietDAO gebietDAO;

  @Inject
  private transient GruppeDAO gruppeDAO;

  public GruppeImGebietGruppenGebieteValidator() {
    super();
  }

  public void pruefeExistenzAlleGruppenUndGebiete(Collection<Gruppe> gruppen, Collection<Gebiet> gebiete, Wahl wahl,
      Violations violations) {
    Collection<Gebiet> gebieteDerWahl = gebietDAO.findByWahl(wahl);
    Map<GebietTK, Gebiet> vorhandeneGebieteNachTKMap = GebietTK.mappeGebietNachTK(gebieteDerWahl);

    Collection<Gruppe> gruppenDerWahl = gruppeDAO.findByWahl(wahl);
    Map<GruppeTK, Gruppe> vorhandeneGruppenNachTKMap = GruppeTK.mappeGruppeNachTK(gruppenDerWahl);

    Set<GebietTK> fehlendeGebiete;
    Set<GruppeTK> fehlendeGruppen;

    fehlendeGebiete = gebiete.stream().map(Gebiet::getGebietTK).filter(gebietTK -> !vorhandeneGebieteNachTKMap.containsKey(gebietTK))
        .collect(Collectors.toSet());

    fehlendeGruppen = gruppen.stream().map(Gruppe::getGruppeTK).filter(gruppeTK -> !vorhandeneGruppenNachTKMap.containsKey(gruppeTK))
        .collect(Collectors.toSet());

    fehlendeGebiete = behandleFehlendeGebiete(wahl, fehlendeGebiete, gebiete, gebieteDerWahl);

    for (GebietTK gebietTK : fehlendeGebiete) {
      violations.add(new GebietNichtGefundenViolation(gebietTK));
    }


    fehlendeGruppen = behandleFehlendeGruppen(wahl, fehlendeGruppen, gruppen, gruppenDerWahl);

    for (GruppeTK gruppeTK : fehlendeGruppen) {
      addGruppeViolation(violations, gruppeTK);
    }
  }

  protected void addGruppeViolation(Violations violations, GruppeTK gruppeTK) {
    if (StringUtils.isBlank(gruppeTK.getSchluessel())) {
      // ELECT-9776
      violations.addError("import.validierung.fehler.gruppe.ohne.schluessel");
    } else {
      addGruppeFehltViolation(violations, gruppeTK);
    }
  }

  protected void addGruppeFehltViolation(Violations violations, GruppeTK gruppeTK) {
    violations.add(new GruppeNichtGefundenViolation(gruppeTK));
  }

  protected Set<GebietTK> behandleFehlendeGebiete(Wahl wahl, Set<GebietTK> fehlendeGebiete, Collection<Gebiet> gebiete, Collection<Gebiet> gebieteDerWahl) {
    return fehlendeGebiete;
  }

  protected Set<GruppeTK> behandleFehlendeGruppen(Wahl wahl, Set<GruppeTK> fehlendeGruppen, Collection<Gruppe> gruppen, Collection<Gruppe> gruppenDerWahl) {
    return fehlendeGruppen;
  }

  public void pruefeExistenzAlleGruppenUndGebiete(Collection<GruppeImGebiet> gruppenImGebiet, Wahl wahl, Violations violations) {
    pruefeExistenzAlleGruppenUndGebiete(gruppenImGebiet.stream().map(GruppeImGebiet::getGruppe).collect(Collectors.toList()),
        gruppenImGebiet.stream().map(GruppeImGebiet::getGebiet).collect(Collectors.toList()), wahl, violations);
  }
}
