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

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import de.ivu.elect.business.gebietsbaum.entity.Wahldurchfuehrungsgebiet;
import de.ivu.elect.business.gruppe.entity.SystemGruppe;
import de.ivu.elect.business.gruppe.entity.SystemGruppeEigenschaften;
import de.ivu.elect.business.gruppeimgebiet.entity.GruppeImGebiet;
import de.ivu.elect.business.stimmeingabe.entity.Ergebniseingangsart;
import de.ivu.elect.business.stimmeingabe.entity.Ergebniseingangsherkunft;
import de.ivu.elect.business.stimmeingabe.entity.Stimmeingabe;
import de.ivu.elect.business.stimmeingabe.entity.Stimmeingabefehler;
import de.ivu.elect.business.wahl.entity.Wahldurchfuehrung;
import de.ivu.elect.jee.entity.EntityUtil;
import de.ivu.elect.jee.entity.tk.EntityTK;
import de.ivu.elect.util.MapBuilder;

/*
 * NOTE, dass einige Ergebnisse GECACHED werden und sich die Werte daher NICHT verändern sollten!
 */
public abstract class AbstractStimmeingabeErfassenContext implements StimmeingabeErfassenContext {

  private Map<EntityTK, Stimmeingabe> stimmeingabenLetzterErgebniseingangPerTk;

  private Map<EntityTK, Stimmeingabe> stimmeingabenVergleichErgebniseingangPerTk;

  private Map<EntityTK, List<Stimmeingabefehler>> stimmeingabefehlerLetzterErgebniseingangPerTk;

  private Map<SystemGruppe, GruppeImGebiet> gruppenImGebietPerSystemGruppe;

  public AbstractStimmeingabeErfassenContext() {
    super();
  }

  @Override
  public boolean isErgebniseingangsartEndgueltig() {
    return isErgebniseingangsart(Ergebniseingangsart.ENDGUELTIG);
  }

  @Override
  public boolean isErgebniseingangsartVorlaeufig() {
    return isErgebniseingangsart(Ergebniseingangsart.VORLAEUFIG);
  }

  @Override
  public boolean isErgebniseingangsart(Ergebniseingangsart ergebniseingangsart) {
    return ergebniseingangsart.equals(getErgebniseingangsart());
  }

  @Override
  public Ergebniseingangsart getErgebniseingangsart() {
    return getErgebniseingang().getErgebniseingangsart();
  }

  @Override
  public boolean isBriefwahlgebiet() {
    if (getWahldurchfuehrungsgebiet() != null) {
      return getWahldurchfuehrungsgebiet().isBriefwahlgebiet();
    }

    return false;
  }

  @Override
  public String getGebietName() {
    if (getWahldurchfuehrungsgebiet() == null) {
      return null;
    }

    return getWahldurchfuehrungsgebiet().getName();
  }

  @Override
  public boolean isLetzterErgebniseingangAktuellGueltig() {
    return hasLetzterErgebniseingangAktuell() && getLetzterErgebniseingangAktuell().isGueltig();
  }

  @Override
  public boolean hasLetzterErgebniseingangAktuell() {
    return getLetzterErgebniseingangAktuell() != null;
  }

  @Override
  public Wahldurchfuehrung getWahldurchfuehrung() {
    return getWahldurchfuehrungsgebiet().getWahldurchfuehrung();
  }

  @Override
  public Wahldurchfuehrungsgebiet getWahldurchfuehrungsgebiet() {
    return getErgebniseingang().getWahldurchfuehrungsgebiet();
  }

  @Override
  public Map<EntityTK, Stimmeingabe> getLetzterErgebniseingangAktuellStimmeingabenPerTk() {
    if (stimmeingabenLetzterErgebniseingangPerTk == null) {
      Collection<Stimmeingabe> stimmeingabenLetzterErgebniseingang = getLetzterErgebniseingangAktuellStimmeingaben();

      if (stimmeingabenLetzterErgebniseingang.isEmpty()) {
        stimmeingabenLetzterErgebniseingang = getLetzterErgebniseingangAktuellVorlaeufigStimmeingaben();
      }

      stimmeingabenLetzterErgebniseingangPerTk = EntityUtil.mappeNachKonkretestemTk(stimmeingabenLetzterErgebniseingang);
    }

    return stimmeingabenLetzterErgebniseingangPerTk;
  }

  @Override
  public Map<EntityTK, List<Stimmeingabefehler>> getLetzterErgebniseingangAktuellStimmeingabefehlerPerTk() {
    if (stimmeingabefehlerLetzterErgebniseingangPerTk == null) {
      stimmeingabefehlerLetzterErgebniseingangPerTk = MapBuilder.newMapMultipleEntriesFrom(getLetzterErgebniseingangAktuellStimmeingabefehler(),
          Stimmeingabefehler.getStimmeingabefehlerToStimmeingabeTkFunction());
    }

    return stimmeingabefehlerLetzterErgebniseingangPerTk;
  }

  @Override
  public Map<EntityTK, Stimmeingabe> getVergleichErgebniseingangStimmeingabenPerTk() {
    if (stimmeingabenVergleichErgebniseingangPerTk == null) {
      stimmeingabenVergleichErgebniseingangPerTk = EntityUtil.mappeNachKonkretestemTk(getVergleichErgebniseingangStimmeingaben());
    }

    return stimmeingabenVergleichErgebniseingangPerTk;
  }

  @Override
  public Map<SystemGruppe, GruppeImGebiet> getGruppenImGebietPerSystemGruppe(SystemGruppeEigenschaften systemGruppeEigenschaften) {
    if (gruppenImGebietPerSystemGruppe == null) {
      gruppenImGebietPerSystemGruppe = new HashMap<>();

      for (GruppeImGebiet gruppeImGebiet : getGruppenImGebiet()) {
        if (gruppeImGebiet.isSystemGruppe()) {
          gruppenImGebietPerSystemGruppe.put(gruppeImGebiet.getGruppe().getSystemGruppe(systemGruppeEigenschaften), gruppeImGebiet);
        }
      }
    }

    return gruppenImGebietPerSystemGruppe;
  }

  @Override
  public Ergebniseingangsherkunft getErgebniseingangsherkunft() {
    return getErgebniseingang().getErgebniseingangsherkunft();
  }
}
