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

import java.util.List;

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

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

import de.ivu.elect.business.gruppe.boundary.EinzelbewerberBoundaryCreate;
import de.ivu.elect.business.gruppe.boundary.GruppeEdit;
import de.ivu.elect.business.gruppe.entity.PolitischeGruppe;
import de.ivu.elect.business.kandidatur.boundary.DirektkandidaturEdit;
import de.ivu.elect.business.protokollierung.entity.LoeschProtokollEvent;
import de.ivu.elect.business.wahlvorschlag.entity.Direktkandidat;
import de.ivu.elect.business.wahlvorschlag.entity.Liste;
import de.ivu.elect.business.wahlvorschlag.entity.Wahlvorschlag;
import de.ivu.elect.presentation.gebietsbaum.GebietNummerFormatter;

@Stateless
public class EinzelbewerberWahlvoschlagEdit {

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

  @Inject
  private transient EinzelbewerberBoundaryCreate einzelbewerberBoundaryCreate;

  @Inject
  private transient WahlvorschlagCommonEdit wahlvorschlagCommonEdit;

  @Inject
  private transient GruppeEdit gruppeEdit;

  @Inject
  private transient ListeDAO listeDAO;

  @Inject
  private transient ListeEdit listeEdit;

  @Inject
  private transient DirektkandidatDAO direktkandidatDAO;

  @Inject
  private transient DirektkandidatEdit direktkandidatEdit;

  @Inject
  private transient DirektkandidaturEdit direktkandidaturEdit;

  @Inject
  private transient LoeschProtokollEvent loeschProtokollEvent;

  @Inject
  private transient GebietNummerFormatter gebietNummerFormatter;

  @Inject
  private transient WahlvorschlagDAO wahlvorschlagDAO;


  public EinzelbewerberWahlvoschlagEdit() {
    super();
  }

  public void save(Liste einzelliste) {
    verifyCompleteEinzelbewerber(einzelliste);

    listeEdit.save(einzelliste);
  }

  public void delete(Liste template) {
    Liste einzelliste = attach(template);

    PolitischeGruppe politischeGruppe = einzelliste.getGruppe();

    listeEdit.delete(einzelliste);

    // ELECT-10904
    listeDAO.flush();
    listeDAO.clear();

    deleteGruppeIncludingGruppenImGebiet(politischeGruppe);
  }

  private Liste attach(Liste template) {
    return listeDAO.attach(template);
  }

  public void save(Direktkandidat einzelkandidat) {
    verifyCompleteEinzelbewerber(einzelkandidat);

    direktkandidatEdit.save(einzelkandidat);
  }

  public void delete(Direktkandidat template) {
    Direktkandidat einzelkandidat = attach(template);

    PolitischeGruppe politischeGruppe = einzelkandidat.getGruppe();

    List<Wahlvorschlag> wahlvorschlaegeDerGruppe = wahlvorschlagDAO.findByGruppe(politischeGruppe);

    if (wahlvorschlaegeDerGruppe.size() > 1) {
      LOG.warn(
          "Die Gruppe dieses Einzelkandidaten ist mit mehreren Wahlvorschlaegen verknuepft! Gruppe: " + politischeGruppe + ", " + wahlvorschlaegeDerGruppe);
    }

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

    // ELECT-1150: kein Aufruf von DirektkandidatEdit.delete(einzelkandidat) mehr, um doppeltes Löschen von Entitäten durch Cascading Delete zu vermeiden!
    deleteDirektkandidatur(einzelkandidat);

    deleteWahlvorschlagsPersonen(einzelkandidat); // ELECT-10755

    // ELECT-10904
    direktkandidatDAO.flush();
    direktkandidatDAO.clear();

    if (wahlvorschlaegeDerGruppe.size() > 1) {
      LOG.info("Gruppe hat weitere Wahlvorschlae, lösche nur Einzelkandidat");
      direktkandidatDAO.remove(direktkandidatDAO.attach(einzelkandidat)); // Fehlt, wenn mit WASDE-2091 die Gruppen nicht mehr gelöscht werden
    } else {
      // WASDE-2091
      LOG.info("Gruppe hat keine weiteren Wahlvorschlaege, lösche Gruppe");
      deleteGruppeIncludingGruppenImGebiet(politischeGruppe);
    }
  }

  private Direktkandidat attach(Direktkandidat template) {
    return direktkandidatDAO.attach(template);
  }

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

  private void deleteWahlvorschlagsPersonen(Wahlvorschlag einzelbewerber) {
    wahlvorschlagCommonEdit.deleteWahlvorschlagsPersonen(einzelbewerber);
  }

  private void deleteGruppeIncludingGruppenImGebiet(PolitischeGruppe politischeGruppe) {
    gruppeEdit.delete(politischeGruppe);
  }

  private void verifyCompleteEinzelbewerber(Wahlvorschlag einzelbewerber) {
    einzelbewerberBoundaryCreate.verifyCompleteEinzelbewerber(einzelbewerber);
  }
}
