
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.control.ImporterFindVorhandeneGruppeVerhalten;
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.HashSet;
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, ImporterFindVorhandeneGruppeVerhalten findVorhandeneGruppeVerhalten) {
    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, findVorhandeneGruppeVerhalten);

    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, ImporterFindVorhandeneGruppeVerhalten findVorhandeneGruppeVerhalten) {

    if (ImporterFindVorhandeneGruppeVerhalten.ERST_SCHLUESSEL_DANN_KURZNAME.equals(findVorhandeneGruppeVerhalten)) {
      // ELECTKOM-405
      Set<GruppeTK> result = new HashSet<>();

      if (!fehlendeGruppen.isEmpty()) {
        for (Gruppe gruppe : gruppen) {
          if (fehlendeGruppen.contains(gruppe.getGruppeTK())) {
            for (Gruppe gruppeInDb : gruppenDerWahl) {
              String kurzname = gruppeInDb.getKurzname();
              if (StringUtils.isNotBlank(kurzname)){
                if (kurzname.equalsIgnoreCase(gruppe.getKurzname())||kurzname.equalsIgnoreCase(gruppe.getSchluessel())){
                  gruppe.setSchluessel(gruppeInDb.getSchluessel());
                }
              }
            }
          }

          if (fehlendeGruppen.contains(gruppe.getGruppeTK())){
            result.add(gruppe.getGruppeTK());
          }
        }
      }

      return result;
    }

    return fehlendeGruppen;
  }

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