
package de.ivu.elect.business.wahlvorschlag.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.gruppeimgebiet.entity.GruppeImGebiet;
import de.ivu.elect.business.kandidatur.boundary.DirektkandidaturDAO;
import de.ivu.elect.business.kandidatur.boundary.DirektkandidaturEdit;
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.protokollierung.entity.LoeschProtokollEvent;
import de.ivu.elect.business.wahlvorschlag.entity.Direktkandidat;
import de.ivu.elect.business.wahlvorschlag.entity.WahlvorschlagStatus;
import de.ivu.elect.presentation.gebietsbaum.GebietNummerFormatter;

@Stateless
public class DirektkandidatEdit extends AbstractDirektkandidatEdit {

  @Inject
  private transient DirektkandidaturDAO direktkandidaturDAO;

  @Inject
  private transient WahlvorschlagCommonEdit wahlvorschlagCommonEdit;

  @Inject
  private transient DirektkandidaturEdit direktkandidaturEdit;

  @Inject
  private transient GewaehltCreate gewaehltCreate;

  @Inject
  private transient KandidaturPruefungAttributeChangedChecker personenPruefungAttributeChangedChecker;

  @Inject
  private transient CorePersonenPruefungVorbereiter personenPruefungVorbereiter;

  @Inject
  private transient PersonenPruefungStarter personenPruefungStarter;

  @Inject
  private transient LoeschProtokollEvent loeschProtokollEvent;

  @Inject
  private transient GebietNummerFormatter gebietNummerFormatter;

  public DirektkandidatEdit() {
    super();
  }

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

  @Override
  public void save(Direktkandidat direktkandidat) {
    saveAndUpdateGruppeImGebiet(direktkandidat, direktkandidat.getGruppeImGebiet());
  }

  private void saveAndUpdateGruppeImGebiet(Direktkandidat direktkandidat, GruppeImGebiet gruppeImGebiet) {
    Direktkandidatur direktkandidatur = direktkandidat.getDirektkandidatur();

    updateGruppeImGebietPreSave(direktkandidat, gruppeImGebiet);

    updateDirektkandidatur(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(direktkandidat);

    // 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(direktkandidaturDAO.refresh(direktkandidatur), personenPruefungAttributeChangedChecker);

    personenPruefungStarter.startePersonenPruefung();
  }

  private void updateGruppeImGebietPreSave(Direktkandidat direktkandidat, GruppeImGebiet gruppeImGebiet) {
    wahlvorschlagCommonEdit.updateGruppeImGebietPreSave(direktkandidat, gruppeImGebiet);
  }

  private void updateDirektkandidatur(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<Direktkandidat> direktkandidaten) {
    for (Direktkandidat direktkandidat : new ArrayList<>(direktkandidaten)) {
      delete(direktkandidat);
    }
  }

  @Override
  public void delete(Direktkandidat template) {
    Direktkandidat direktkandidat = getAttachedEntity(template);

    loeschProtokollEvent.sendeLoeschProtokollEvent(direktkandidat.getWahl(), direktkandidat, "loesch.protokoll.direktkandidat", direktkandidat.getGruppe().getName(),
        gebietNummerFormatter.getDarstellung(direktkandidat.getGebiet()));

    GruppeImGebiet gruppeImGebiet = direktkandidat.getGruppeImGebiet();

    deleteDirektkandidatur(direktkandidat);
    deleteWahlvorschlagsPersonen(direktkandidat); // ELECT-10755

    wahlvorschlagCommonEdit.updateGruppeImGebietPreDelete(direktkandidat, gruppeImGebiet);

    super.delete(direktkandidat);

    wahlvorschlagCommonEdit.updateGruppeImGebietPostDelete(gruppeImGebiet);
  }

  private void deleteDirektkandidatur(Direktkandidat direktkandidat) {
    direktkandidaturEdit.delete(direktkandidat.getDirektkandidatur());
  }

  private void deleteWahlvorschlagsPersonen(Direktkandidat direktkandidat) {
    wahlvorschlagCommonEdit.deleteWahlvorschlagsPersonen(direktkandidat);
  }

  public void setStatus(Direktkandidat direktkandidat, WahlvorschlagStatus wahlvorschlagStatus, String wahlvorschlagStatusBemerkung) {
    wahlvorschlagCommonEdit.setStatus(direktkandidat, wahlvorschlagStatus);
  }
}
