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

import de.ivu.elect.business.gebietsbaum.control.AWerteAktualisierer;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.gebietsbaum.entity.GebietUebernehmenContext;
import de.ivu.elect.business.gebietsbaum.entity.Wahldurchfuehrungsgebiet;
import de.ivu.elect.business.replikation.boundary.ReplikationErzeugen;
import de.ivu.elect.business.wahl.boundary.WahlDAO;
import de.ivu.elect.business.wahl.boundary.WahlExtendedDAO;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.ejb.Stateless;
import javax.enterprise.inject.Specializes;
import javax.inject.Inject;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;


import static de.ivu.elect.jee.entity.EntityUtil.castTo;

@Specializes
@Stateless
public class WasGebietEdit extends CoreGebietEdit {

  private static final Logger LOG = LoggerFactory.getLogger(WasGebietEdit.class);

  @Inject
  private transient WahlDAO wahlDAO;

  @Inject
  private transient WahlExtendedDAO wahlExtendedDAODAO;

  @Inject
  private transient WahldurchfuehrungsgebietExtendedDAO wahldurchfuehrungsgebietExtendedDAO;

  @Inject
  private transient WahldurchfuehrungsgebietDAO wahldurchfuehrungsgebietDAO;

  @Inject
  private transient ReplikationErzeugen replikationErzeugen;

  @Inject
  private transient GebietUebernehmen gebietUebernehmen;

  @Inject
  private transient WasGebietEditHelper wasGebietEditHelper;

  public WasGebietEdit() {
    super();
  }

  @Override
  public void save(Gebiet entity) {
    Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet = castTo(entity, Wahldurchfuehrungsgebiet.class);

    AWerteAktualisierer aWerteAktualisierer = new AWerteAktualisierer(
        wahldurchfuehrungsgebiet.getWahl(),
        wahldurchfuehrungsgebietExtendedDAO,
        wasGebietEditHelper.getUmgangHinterlegteAWerte(wahldurchfuehrungsgebiet.getWahl()));

    aWerteAktualisieren(wahldurchfuehrungsgebiet, aWerteAktualisierer);

    super.save(entity);

    Set<Gebiet> zielGebieteBeiAufteilung = entity.getZielGebieteBeiAufteilung(wahlExtendedDAODAO, extendedDao);
    for (Gebiet zielGebiet : zielGebieteBeiAufteilung) {
      Wahldurchfuehrungsgebiet zielWahldurchfuehrungsgebiet = wahldurchfuehrungsgebietExtendedDAO.findByPrimaryKey(zielGebiet.getPk());

      GebietUebernehmenContext uebernehmenContext = new GebietUebernehmenContext(false /* nicht benötigt in ziel */, true, false /* lieber mal nicht */,
          true/*legacy*/, false/* ELECTKOM-631 A-Werte nicht mehr übernehmen */);
      gebietUebernehmen.kopierereGebietUnveraendert(wahldurchfuehrungsgebiet, zielWahldurchfuehrungsgebiet, uebernehmenContext);

      //      aWerteAktualisieren(zielWahldurchfuehrungsgebiet, aWerteAktualisierer); /* ELECTKOM-631 A-Werte nicht mehr übernehmen*/

    }
    if (!zielGebieteBeiAufteilung.isEmpty()) {
      flushToSave();
    }

    if (replikationErzeugen.isReplikationNotwendig()) {
      List<Wahldurchfuehrungsgebiet> zuReplizieren = new ArrayList<>();

      Gebiet gebiet = wahldurchfuehrungsgebiet;

      while (gebiet != null) {
        zuReplizieren.add(wahldurchfuehrungsgebietExtendedDAO.refresh(wahldurchfuehrungsgebietExtendedDAO.findByPrimaryKey(gebiet.getId())));
        gebiet = gebiet.getUebergeordnetesGebiet();
      }

      replikationErzeugen.replikationGebietUpdate(zuReplizieren);
    }
  }

  @Override
  public void delete(Gebiet entity) {
    Gebiet gebiet = dao.attach(entity);

    AWerteAktualisierer aWerteAktualisierer = new AWerteAktualisierer(gebiet.getWahl(), wahldurchfuehrungsgebietDAO,
        wasGebietEditHelper.getUmgangHinterlegteAWerte(gebiet.getWahl()));

    aWerteZuruecksetzen(gebiet, aWerteAktualisierer);

    for (Gebiet zielGebiet : gebiet.getZielGebieteBeiAufteilung(wahlDAO, dao)) {
      aWerteZuruecksetzen(zielGebiet, aWerteAktualisierer);
      LOG.info("Lösche Gebiet: " + zielGebiet + " in Wahl: " + zielGebiet.getWahl());
      super.delete(zielGebiet);
    }

    super.delete(entity);
  }

  private void aWerteZuruecksetzen(Gebiet gebiet, AWerteAktualisierer aWerteAktualisierer) {
    Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet = castTo(gebiet, Wahldurchfuehrungsgebiet.class);
    wahldurchfuehrungsgebiet.setAnzahlWahlberechtigteOhneWahlschein(null);
    wahldurchfuehrungsgebiet.setAnzahlWahlberechtigteMitWahlschein(null);
    wahldurchfuehrungsgebiet.setAnzahlWahlberechtigteNichtImWaehlerverzeichnis(null);

    aWerteAktualisieren(wahldurchfuehrungsgebiet, aWerteAktualisierer);
  }

  private void aWerteAktualisieren(Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet, AWerteAktualisierer aWerteAktualisierer) {
    if (wahldurchfuehrungsgebiet.hasChangedAnzahlWahlberechtigteOhneWahlschein() || wahldurchfuehrungsgebiet.hasChangedAnzahlWahlberechtigteMitWahlschein()
        || wahldurchfuehrungsgebiet.hasChangedAnzahlWahlberechtigteNichtImWaehlerverzeichnis()) {
      aWerteAktualisierer.aktualisiereAWerteFuerUebergeordneteGebieteVon(wahldurchfuehrungsgebiet);
    }
  }
}
