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

import java.util.ArrayList;
import java.util.Collection;

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

import de.ivu.elect.business.ergebnis.control.GewaehltCreate;
import de.ivu.elect.business.ergebnis.entity.Gewaehlt;
import de.ivu.elect.business.kandidatur.entity.Direktkandidatur;
import de.ivu.elect.business.personenpruefung.boundary.PersonenPruefungStarter;
import de.ivu.elect.business.personenpruefung.control.CorePersonenPruefungVorbereiter;
import de.ivu.elect.business.personenpruefung.control.KandidaturPruefungAttributeChangedChecker;
import de.ivu.elect.business.wahlvorschlag.entity.Direktkandidat;

@Stateless
public class DirektkandidaturEdit extends AbstractDirektkandidaturEdit {

  @Inject
  protected transient GewaehltCreate gewaehltCreate;

  @Inject
  protected transient KandidaturPruefungAttributeChangedChecker personenPruefungAttributeChangedChecker;

  @Inject
  protected transient CorePersonenPruefungVorbereiter personenPruefungVorbereiter;

  @Inject
  protected transient PersonenPruefungStarter personenPruefungStarter;

  @Inject
  protected transient ErsatzkandidaturEdit ersatzkandidaturEdit;

  public DirektkandidaturEdit() {
    super();
  }

  @Override
  protected boolean usesMixedTransactionalContexts() {
    // ELECT-945, bspw. GewaehltDAO!
    return true;
  }

  @Override
  public void save(Direktkandidatur direktkandidatur) {
    verifyCompleteDirektkandidatur(direktkandidatur);

    // NOTE ELECT-2749, dass Änderungen festgestellt werden müssen, bevor die Entität gespeichert wird
    personenPruefungAttributeChangedChecker.bestimmeAttributeChanged(direktkandidatur);

    // NOTE that the super implementation performs an ExtendedDao.flush()!
    super.save(direktkandidatur);

    // NOTE ELECT-2749, dass die Prüfung vorbereitet werden muss, nachdem die Entität gespeichert wurde
    // NOTE bzgl. attachFresh: ELECT-3187 (Änderungen an Entität werden nicht gespeichert)
    personenPruefungVorbereiter.prepareKandidaturPruefung(dao.refresh(direktkandidatur), personenPruefungAttributeChangedChecker);

    personenPruefungStarter.startePersonenPruefung();
  }

  private void verifyCompleteDirektkandidatur(Direktkandidatur direktkandidatur) {
    // NOTE ELECT-485, bisher nicht erfasste Ergebnisse werden beim (manuellen) Bearbeiten ggf. neu angelegt.
    for (Gewaehlt gewaehlt : direktkandidatur.getGewaehlte()) {
      if (!gewaehlt.isPersistent()) {
        gewaehltCreate.save(gewaehlt);
      }
    }
  }

  public void delete(Collection<Direktkandidatur> direktkandidaturen) {
    for (Direktkandidatur direktkandidatur : new ArrayList<>(direktkandidaturen)) {
      delete(direktkandidatur);
    }
  }

  /**
   * Diese Methode löscht keine Direktkandidaten sondern nur Direktkandidatur.
   *
   * Falls der Kandidat gelöscht werden soll, dann bitte die Klasse DirektkandidatEdit nutzen.
   */
  @Override
  public void delete(Direktkandidatur template) {
    Direktkandidatur direktkandidatur = getAttachedEntity(template);

    deleteIncludingAllUntergeordneteErsatzkandidaturen(direktkandidatur); // ELECT-9845, zunächst alle Ersatzkandidaturen löschen...

    Direktkandidat direktkandidat = direktkandidatur.getDirektkandidat();
    direktkandidat.setDirektkandidatur(null);
  }

  private void deleteIncludingAllUntergeordneteErsatzkandidaturen(Direktkandidatur direktkandidatur) {
    if (direktkandidatur.hasZugeordneteErsatzkandidatur()) {
      ersatzkandidaturEdit.delete(direktkandidatur.getZugeordneteErsatzkandidatur());
    }

    personenPruefungVorbereiter.deleteAllVerknuepfungenAndMarkVerknuepftePersonenUngeprueft(direktkandidatur);

    super.delete(direktkandidatur);

    personenPruefungStarter.startePersonenPruefung();
  }
}
