package de.ivu.elect.business.stimmeingabe.control;

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

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

import de.ivu.elect.business.gebietsbaum.entity.GebietPK;
import de.ivu.elect.business.stimmeingabe.entity.Ergebniseingang;
import de.ivu.elect.business.stimmeingabe.entity.Ergebniseingangsart;
import de.ivu.elect.business.stimmeingabe.entity.LetzterEingang;
import de.ivu.elect.business.wahl.entity.WahlPK;

public class LetzterEingangCache implements Serializable {

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

  private static final long serialVersionUID = 1L;

  private static final Map<WahlPK, Map<GebietPK, Map<Ergebniseingangsart, LetzterEingang>>> CACHE = new ConcurrentHashMap<>();

  public void setzeLetztenEingangWennNeuer(Ergebniseingang ergebniseingang) {
    if (ergebniseingang==null || ergebniseingang.getWahldurchfuehrungsgebiet()==null || ergebniseingang.getWahldurchfuehrungsgebiet().getWahl() ==null) {
      return;
    }

    WahlPK wahlPK = ergebniseingang.getWahldurchfuehrungsgebiet().getWahl().getPk();
    GebietPK gebietPK = ergebniseingang.getWahldurchfuehrungsgebiet().getPk();
    LetzterEingang bisJetzt = getLetzterEingang(wahlPK, gebietPK, ergebniseingang.getErgebniseingangsart());

    if (bisJetzt.getEingangssequenznummer()<(ergebniseingang.getEingangssequenznummer())) {
      getEingangMap(wahlPK, gebietPK).put(ergebniseingang.getErgebniseingangsart(), new LetzterEingang(ergebniseingang.getPk(),
          ergebniseingang.getEingangssequenznummer(), ergebniseingang.getErgebniseingangsfehlerstatus(), ergebniseingang.getZeitstempel(), ergebniseingang.isInErgebnisUebernehmbar()));
    }
  }

  public LetzterEingang setzeNichtVorhanden(WahlPK wahlPK, GebietPK gebietPK, Ergebniseingangsart ergebniseingangsart) {
    return getEingangMap(wahlPK, gebietPK).computeIfAbsent(ergebniseingangsart, x->LetzterEingang.KEIN_EINGANG);
  }

  public LetzterEingang getLetzterEingang(WahlPK wahlPK, GebietPK gebietPK, Ergebniseingangsart ergebniseingangsart) {
    return getEingangMap(wahlPK, gebietPK).getOrDefault(ergebniseingangsart, LetzterEingang.UNBEKANNT);
  }

  private Map<Ergebniseingangsart, LetzterEingang> getEingangMap(WahlPK wahlPK, GebietPK gebietPK) {
    return CACHE.computeIfAbsent(wahlPK, x -> new ConcurrentHashMap<>()).computeIfAbsent(gebietPK, x -> new EnumMap<>(Ergebniseingangsart.class));
  }

  public void reset(WahlPK wahlPK, GebietPK gebietPK) {
    CACHE.computeIfAbsent(wahlPK, x->new ConcurrentHashMap<>()).remove(gebietPK);
  }

  public void reset(WahlPK wahlPK) {
    CACHE.remove(wahlPK);
  }

  public void resetCache() {
    LOG.info("Reset Cache");
    CACHE.clear();
  }
}
