
package de.ivu.elect.business.wahlrechtspruefung.entity;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

import javax.annotation.Nullable;
import javax.persistence.Transient;

import de.ivu.elect.business.gebietsbaum.entity.EntityMitGebiet;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.kandidatur.entity.Kandidatur;
import de.ivu.elect.business.wahlvorschlag.entity.Wahlvorschlag;

public abstract class AbstractWahlrechtspruefung implements WahlrechtspruefungBase, EntityMitGebiet {

  private static final long serialVersionUID = 1L;

  public AbstractWahlrechtspruefung() {
    super();
  }

  public boolean isZulassenErlaubt() {
    return getWahlrechtspruefStatus().isZulassenErlaubt(getPruefkriterium());
  }

  protected void preSetWahlrechtspruefStatus(WahlrechtspruefStatus alterWert, WahlrechtspruefStatus neuerWert) {
    // nichts zu tun
  }

  protected void postSetWahlrechtspruefStatus(WahlrechtspruefStatus alterWert, WahlrechtspruefStatus neuerWert) {
    if (neuerWert != null && wertHatSichGeaendert(alterWert, neuerWert)) {
      // Wenn der neue Status dazu führt, dass die Kandidatur oder der Wahlvorschlag nicht mehr zugelassen werden können, diese aber bereits zugelassen sind, setze der Status wieder auf ungeprueft
      if (getPruefkriterium() != null && !neuerWert.isZulassenErlaubt(getPruefkriterium())) {
        Wahlvorschlag wahlvorschlag = getWahlvorschlag();
        Kandidatur kandidatur = getKandidatur();
        
        if (wahlvorschlag != null && kandidatur == null /*ELECT-13851*/ && wahlvorschlag.isZugelassen()) {
          wahlvorschlag.setWahlvorschlagStatus(wahlvorschlag.getWahlvorschlagStatusInitial());
        }

        if (kandidatur != null && kandidatur.isZugelassen()) {
          kandidatur.setKandidaturStatus(kandidatur.getKandidaturStatusInitial());
        }
      }
    }
  }

  protected WahlrechtspruefStatus preProcessWahlrechtspruefStatus(WahlrechtspruefStatus neuerWert) {
    return neuerWert;
  }

  protected <T> boolean wertHatSichGeaendert(T alterWert, T neuerWert) {
    return !Objects.equals(alterWert, neuerWert);
  }

  @Nullable
  @Override
  public Gebiet getGebiet() {
    if (getKandidatur() != null) {
      return getKandidatur().getGebiet();
    }

    if (getWahlvorschlag() != null) {
      return getWahlvorschlag().getGebiet();
    }

    return null;
  }

  @Transient
  private transient Map<String, Object> instanceCache = null;

  public Map<String, Object> getInstanceCache() {
    if (instanceCache == null) {
      instanceCache = new HashMap<>();
    }
    return instanceCache;
  }
}
