package de.ivu.elect.presentation.wahlvorschlag;

import java.io.Serializable;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.enterprise.event.Observes;
import javax.enterprise.event.Reception;
import javax.enterprise.event.TransactionPhase;
import javax.inject.Inject;

import org.apache.deltaspike.core.api.scope.ViewAccessScoped;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import de.ivu.elect.business.kandidatur.boundary.ListenkandidaturExtendedDAO;
import de.ivu.elect.business.stimmzettel.boundary.EntityAufStimmzettelDatenExtendedDAOFactory;
import de.ivu.elect.business.wahlrechtspruefung.boundary.WahlrechtspruefungExtendedDAO;
import de.ivu.elect.business.wahlvorschlag.boundary.ListeExtendedDAO;
import de.ivu.elect.business.wahlvorschlag.entity.Liste;
import de.ivu.elect.business.wahlvorschlag.entity.NlListe;
import de.ivu.elect.business.wahlvorschlag.entity.NlListeStatus;
import de.ivu.elect.business.wahlvorschlag.entity.StelInformationen;
import de.ivu.elect.business.wahlvorschlag.entity.WahlvorschlagPK;

@ViewAccessScoped // TODO mal schauen, ob das gut geht...
public class NlListeStelInformationCache implements Serializable {

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

  private static final long serialVersionUID = 1L;

  @Inject
  private transient ListeExtendedDAO listeExtendedDAO;

  @Inject
  private transient EntityAufStimmzettelDatenExtendedDAOFactory entityAufStimmzettelDatenExtendedDAOFactory;

  @Inject
  private transient WahlrechtspruefungExtendedDAO wahlrechtspruefungExtendedDAO;

  @Inject
  private transient ListenkandidaturExtendedDAO listenkandidaturExtendedDAO;

  private final Map<WahlvorschlagPK, StelInformationen> stelInformationenCache = new ConcurrentHashMap<>();

  private final Map<WahlvorschlagPK, NlListeStatus> listeStatusCacheCache = new ConcurrentHashMap<>();

  public StelInformationen getStelInformationen(Liste liste) {
    if (liste == null) {
      return StelInformationen.createUnbekannt(null);
    }
    return stelInformationenCache.computeIfAbsent(liste.getPk(), x -> NlListe.getStelInformationen(liste, listeExtendedDAO.findByGruppe(liste.getGruppe()),
        entityAufStimmzettelDatenExtendedDAOFactory.getEntityAufStimmzettelDaten(), listenkandidaturExtendedDAO));
  }

  public NlListeStatus getNlListeStatus(Liste liste) {
    if (liste == null) {
      return NlListeStatus.OFFEN; // irgendwas als fallback..
    }

    // kein Cache für triviale Informationen
    if (liste.getWahlvorschlagStatus().isZugelassen()) {
      return NlListeStatus.ZUGELASSEN;
    }
    if (liste.getWahlvorschlagStatus().isNichtZugelassenImSinneAbgelehnt()) {
      return NlListeStatus.ABGELEHNT;
    }

    return listeStatusCacheCache.computeIfAbsent(liste.getPk(), x -> NlListe.getNlListeStatus(liste, wahlrechtspruefungExtendedDAO));
  }

  public void listen(@Observes(during = TransactionPhase.AFTER_SUCCESS, notifyObserver = Reception.IF_EXISTS) NlListeStelInformationChangeEvent event) {
    reset();
  }

  private void reset() {
    // LOG.info("reset");
    stelInformationenCache.clear();
    listeStatusCacheCache.clear();
  }

}
