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

import static de.ivu.elect.jee.entity.EntityUtil.castTo;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

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

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

import de.ivu.elect.business.kandidatur.boundary.ListenkandidaturDAO;
import de.ivu.elect.business.kandidatur.boundary.ListenkandidaturEdit;
import de.ivu.elect.business.kandidatur.control.NlListenkandidaturSynchronisieren;
import de.ivu.elect.business.kandidatur.entity.KandidaturStatus;
import de.ivu.elect.business.kandidatur.entity.Listenkandidatur;
import de.ivu.elect.business.person.entity.PersonStatus;
import de.ivu.elect.business.person.entity.Personendaten;
import de.ivu.elect.business.person.entity.PersonenregisterAbgleichStatus;
import de.ivu.elect.business.personenpruefung.entity.PersonenKonflikt;
import de.ivu.elect.business.personenpruefung.entity.PersonenKonfliktArt;
import de.ivu.elect.business.personenpruefung.entity.PersonenKonfliktStatus;
import de.ivu.elect.business.wahl.entity.Wahl;

@Stateless
@Specializes
public class NlPersonenKonfliktEdit extends PersonenKonfliktEdit {

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

  @Inject
  private transient ListenkandidaturDAO listenkandidaturDAO;

  @Inject
  private transient ListenkandidaturEdit listenkandidaturEdit;

  @Inject
  private transient NlListenkandidaturSynchronisieren nlListenkandidaturSynchronisieren;

  public NlPersonenKonfliktEdit() {
    super();
  }

  // ELECT-11211
  public void saveListenkandidaturZulassungAblehnenMitBemerkung(PersonenKonflikt personenKonflikt, KandidaturStatus kandidaturStatus, String kandidaturStatusBemerkung) {
    Collection<PersonenKonflikt> personenKonflikte = asList(personenKonflikt);

    saveAll(personenKonflikte);
    updatePersonendatenAndKonflikt(PersonStatus.GEEIGNET, PersonenKonfliktStatus.IRRELEVANT, personenKonflikte);

    Personendaten personendaten = getAttachedEntity(personenKonflikt).getPersonendaten();

    if (personendaten.isInstanceOf(Listenkandidatur.class)) {
      listenkandidaturEdit.setStatus(castTo(personendaten, Listenkandidatur.class), kandidaturStatus, kandidaturStatusBemerkung);
    }
  }

  public void deletePersonenKonfliktAndRestartPersonenPruefung(Wahl wahl) {
    long tic = System.currentTimeMillis();
    List<Personendaten> personendaten = new ArrayList<>(listenkandidaturDAO.findByWahl(wahl));
    LOG.info("Listenkandidaturen geladen nach " + (System.currentTimeMillis() - tic) / 1000 + "s");

    List<PersonenKonflikt> konflikte = dao.findByWahlAndKonfliktArtAndKonfliktStatus(wahl, Collections.singletonList(PersonenKonfliktArt.ABGLEICH_FEHLGESCHLAGEN),
        Arrays.asList(PersonenKonfliktStatus.values()));
    LOG.info(personendaten.size() + " Listenkandidaturen wurden geladen.");
    LOG.info(konflikte.size() + " Konflikte wurden geladen.");

    tic = System.currentTimeMillis();
    for (PersonenKonflikt konflikt : konflikte) {
      if (personendaten.contains(konflikt.getPersonendaten())) {
        dao.remove(konflikt);
      }
    }
    LOG.info("Konflikte gelöscht nach " + (System.currentTimeMillis() - tic) / 1000 + "s");

    tic = System.currentTimeMillis();
    for (Personendaten person : personendaten) {
      person.setPersonStatus(PersonStatus.UNGEPRUEFT);
      person.setPersonenregisterAbgleichStatus(PersonenregisterAbgleichStatus.ABGLEICH_NOTWENDIG);
    }

    LOG.info("Listenkandidaturen aktualisiert nach " + (System.currentTimeMillis() - tic) / 1000 + "s");

    startePersonenPruefung();
  }

  @Override
  public void updatePersonendatenAndKonflikt(PersonStatus personStatus, PersonenKonfliktStatus konfliktStatus, Collection<PersonenKonflikt> konflikte) {
    if (konflikte.size() == 1) {
      PersonenKonflikt konfliktBearbeitet = getAttachedEntity(konflikte.iterator().next());
      PersonenKonfliktArt personenKonfliktArt = konfliktBearbeitet.getPersonenKonfliktArt();

      if (PersonenKonfliktArt.ABGLEICH_FEHLGESCHLAGEN.equals(personenKonfliktArt)) {
        LOG.info("Aktualisiere Konflikt {}", konfliktBearbeitet);

        Personendaten personendatenBearbeitet = konfliktBearbeitet.getPersonendaten();

        LOG.info("\t Synchronisiere verknuepfte Personendaten");
        nlListenkandidaturSynchronisieren.synchronisiereVerknuepftePersonen(personendatenBearbeitet, false /* Status nich geändert... */, false /* Position nicht verändert... */ ,
            false /* Personenprüfung wird am Ende eh gestartet... */ );

        for (Personendaten personendatenVerknuepft : personendatenBearbeitet.getIdentischVerknuepftePersonen()) {
          List<PersonenKonflikt> konflikteVerknuepft = dao.findByPersonAndKonfliktArt(personendatenVerknuepft, singletonList(personenKonfliktArt));

          for (PersonenKonflikt konfliktVerknuepft : konflikteVerknuepft) {
            LOG.info("\t Synchronisiere verknuepften Konflikt");
            konfliktBearbeitet.copyEntityAttributesUsingSetter(konfliktVerknuepft);

            updatePersonendatenAndKonfliktInternal(personStatus, konfliktStatus, konfliktVerknuepft);
          }
        }
      }
    }

    super.updatePersonendatenAndKonflikt(personStatus, konfliktStatus, konflikte);
  }
}
