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

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;

import javax.inject.Inject;

import de.ivu.elect.business.gebietsbaum.boundary.GebietDAO;
import de.ivu.elect.business.gebietsbaum.boundary.GebietsartDAO;
import de.ivu.elect.business.gebietsbaum.boundary.GebietsarteigenschaftDAO;
import de.ivu.elect.business.gebietsbaum.entity.Gebietsart;
import de.ivu.elect.business.gebietsbaum.entity.GebietsartBezirksart;
import de.ivu.elect.business.gebietsbaum.entity.GebietsartTK;
import de.ivu.elect.business.gebietsbaum.entity.Gebietsarteigenschaft;
import de.ivu.elect.business.mandant.entity.Mandant;
import de.ivu.elect.business.wahl.boundary.WahlartDAO;
import de.ivu.elect.business.wahl.boundary.WahlkonfigurationAnpassbar;
import de.ivu.elect.business.wahl.entity.Wahlart;

public class GebietsarteigenschaftFuerWahlartCreator implements Serializable {

  private static final long serialVersionUID = 1L;

  @Inject
  private transient GebietsarteigenschaftDAO gebietsarteigenschaftDAO;

  @Inject
  private transient GebietsartDAO gebietsartDAO;

  @Inject
  private transient GebietDAO gebietDAO;

  @Inject
  private transient WahlartDAO wahlartDAO;

  @Inject
  private transient WahlkonfigurationAnpassbar wahlkonfigurationAnpassbar;

  public GebietsarteigenschaftFuerWahlartCreator() {
    super();
  }

  public Set<GebietsartTK> aktualisiereGebietsarteigenschaften(Wahlart wahlart, Set<Gebietsart> gebietsartenAusgewaehlt) {
    Set<Gebietsart> anzulegende = new HashSet<>(gebietsartDAO.attachAll(gebietsartenAusgewaehlt));

    Mandant mandant = wahlart.getMandant();

    if (!wahlkonfigurationAnpassbar.isWahlkonfigurationAnpassbar(mandant)) {
      return anzulegende.stream().map(Gebietsart::getGebietsartTK).collect(Collectors.toSet()); // nichts zu tun
    }

    Set<Gebietsart> nichtZuLoeschende = new HashSet<>();
    Set<Gebietsarteigenschaft> zuloeschenendeGebietsarteigenschaften = new HashSet<>();

    for (Gebietsarteigenschaft gebietsarteigenschaft : gebietsarteigenschaftDAO.findByAll(mandant)) {
      if (gebietsarteigenschaft.getWahlart().equals(wahlart)) {
        if (anzulegende.contains(gebietsarteigenschaft.getGebietsart())) {
          anzulegende.remove(gebietsarteigenschaft.getGebietsart());
        } else {
          if (isGebietMitGebietsartInWahlartVorhanden(gebietsarteigenschaft.getGebietsart(), gebietsarteigenschaft.getWahlart())) {
            // löschen nicht möglich
            nichtZuLoeschende.add(gebietsarteigenschaft.getGebietsart()); // Gebietsart muss aufgenommen werden
          } else {
            zuloeschenendeGebietsarteigenschaften.add(gebietsarteigenschaft);
          }
        }
      }
    }

    for (Gebietsarteigenschaft gebietsarteigenschaft : zuloeschenendeGebietsarteigenschaften) {
      gebietsarteigenschaftDAO.remove(gebietsarteigenschaft);
    }

    Wahlart wahlartAttached = wahlartDAO.attach(wahlart);

    for (Gebietsart gebietsart : anzulegende) {
      createGebietsarteigenschaft(wahlartAttached, gebietsart);
    }

    return new HashSet<>(nichtZuLoeschende.stream().map(Gebietsart::getGebietsartTK).collect(Collectors.toList()));
  }

  private boolean isGebietMitGebietsartInWahlartVorhanden(Gebietsart gebietsart, Wahlart wahlart) {
    return gebietDAO.findByCountWahlartGebietsart(wahlart, gebietsart) > 0L;
  }

  private void createGebietsarteigenschaft(Wahlart wahlart, Gebietsart gebietsart) {
    Gebietsarteigenschaft gebietsarteigenschaft = new Gebietsarteigenschaft();
    gebietsarteigenschaft.setWahlartOhneUpdateBeziehung(wahlart);
    gebietsarteigenschaft.setGebietsart(gebietsart);
    gebietsarteigenschaft.setErgebnisRelevantDeprecated(true); // ELECT-7331 immer wahr, nur für Destatis Berlin/Ost-West 'sinnvoll' auf "false" zu setzen, hinfällig mit ELECT-8198...

    GebietsartBezirksart gebietsartBezirksart = gebietsart.getBezirksart();

    if (gebietsartBezirksart.isErfassungsgebiet()) {
      gebietsarteigenschaft.setErfassungsgebiet(true);
    }

    if (gebietsartBezirksart.isBriefwahlbezirk()) {
      gebietsarteigenschaft.setBriefwahlgebiet(true);
    }

    gebietsarteigenschaftDAO.persist(gebietsarteigenschaft);
  }
}
