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

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

import javax.annotation.Nullable;

import de.ivu.elect.business.anschrift.entity.Anschrift;
import de.ivu.elect.business.anschrift.entity.EntityMitAnschrift;
import de.ivu.elect.business.ergebnis.entity.AbstractKumulierteStimmen;
import de.ivu.elect.business.ergebnis.entity.Gewaehlt;
import de.ivu.elect.business.ergebnis.entity.Stimmen;
import de.ivu.elect.business.person.entity.PersonendatenPK;
import de.ivu.elect.business.stimmzettel.entity.EntityAufStimmzettelDaten;
import de.ivu.elect.jee.entity.Entity;
import de.ivu.elect.jee.entity.EntityContainer;
import de.ivu.elect.jee.entity.EntityFachlichAbhaengigNode;
import de.ivu.elect.jee.entity.tk.EntityTK;
import de.ivu.elect.jee.protokollierung.VorherNachherWert;

public class KandidaturGewaehlt extends AbstractKumulierteStimmen implements Entity<PersonendatenPK, KandidaturUK>, EntityMitAnschrift {

  private static final long serialVersionUID = 1L;

  private final Kandidatur kandidatur;

  private final Gewaehlt gewaehlt;

  private final Collection<Stimmen> stimmen;

  private Long stimmenAnzahl = null;

  public KandidaturGewaehlt(EntityAufStimmzettelDaten entityAufStimmzettelDaten, Kandidatur kandidatur, Gewaehlt gewaehlt, Collection<Stimmen> stimmen) {
    super(entityAufStimmzettelDaten, 0L, 0L);

    this.kandidatur = kandidatur;
    this.gewaehlt = gewaehlt;
    this.stimmen = stimmen;
  }

  public Long getStimmzettelPosition() {
    return getStimmzettelPosition(getKandidatur());
  }

  @Nullable
  @Override
  public PersonendatenPK getPk() {
    if (kandidatur == null) {
      return null;
    }

    return kandidatur.getPk();
  }

  @Nullable
  @Override
  public Long getId() {
    if (kandidatur == null) {
      return null;
    }
    return kandidatur.getId();
  }

  @Nullable
  @Override
  public KandidaturUK getUk() {
    if (kandidatur == null) {
      return null;
    }

    return kandidatur.getUk();
  }

  @Override
  public Class< ? > getEntityClass() {
    if (kandidatur == null) {
      return getClass();
    }

    return kandidatur.getEntityClass();
  }

  @Override
  public String getEntityTechnicalName() {
    throw new UnsupportedOperationException();
  }

  public Kandidatur getKandidatur() {
    return kandidatur;
  }

  public Gewaehlt getGewaehlt() {
    return gewaehlt;
  }

  public Collection<Stimmen> getStimmen() {
    return stimmen;
  }

  public long getStimmenAnzahl() {
    if (stimmenAnzahl == null) {
      stimmenAnzahl = calculateStimmenAnzahlKumuliert(kandidatur, stimmen);
    }
    return stimmenAnzahl;
  }

  @Override
  public Anschrift getAnschrift() {
    if (getKandidatur()==null) {
      return null;
    }
    return getKandidatur().getAnschrift();
  }

  private static long calculateStimmenAnzahlKumuliert(Kandidatur kandidatur, Collection<Stimmen> stimmen) {

    if (kandidatur.isDirektkandidatur()) {
      return calculateStimmenAnzahlKumuliertDirektkandidatur(kandidatur.castTo(Direktkandidatur.class).getEntity(), stimmen);
    }

    if (kandidatur.isListenkandidatur()) {
      return calculateStimmenAnzahlKumuliertListenkandidatur(kandidatur.castTo(Listenkandidatur.class).getEntity(), stimmen);
    }
    throw new IllegalStateException("Unbekannte Kandidatur: " + kandidatur);
  }

  private static long calculateStimmenAnzahlKumuliertListenkandidatur(Listenkandidatur entity, Collection<Stimmen> stimmen) {
    long result = 0L;

    for (Stimmen value : stimmen) {
      if (value.getListenkandidatur() != null && entity.equals(value.getListenkandidatur())) {
        result += value.getAnzahl();
      }
    }

    return result;
  }

  private static long calculateStimmenAnzahlKumuliertDirektkandidatur(Direktkandidatur direktkandidatur, Collection<Stimmen> stimmen) {
    long result = 0L;

    for (Stimmen value : stimmen) {
      // ELECTDD-313
      if (value.getStimmenart().isDirektstimme() && direktkandidatur.getDirektkandidat().getGebiet().isInGebietshierarchieUebergeordnetesGebietVon(value.getGebiet())) {
        result += value.getAnzahl();
      }
    }

    return result;
  }

  @Override
  public boolean isAenderungenProtokollieren() {
    return false;
  }

  @Override
  public Map<String, VorherNachherWert> getProtokollierteAttributeMitWerten() {
    throw new UnsupportedOperationException();
  }

  @Override
  public void resetProtokollierteAttribute() {
  }

  @Override
  public List<EntityFachlichAbhaengigNode> getFachlichAbhaengigeEntitaeten() {
    throw new UnsupportedOperationException();
  }

  @Override
  public boolean isInstanceOf(Class< ? > clazz) {
    return false;
  }

  @Override
  public <E> EntityContainer<E> castTo(Class<E> clazz) {
    throw new UnsupportedOperationException();
  }

  @Override
  public EntityTK getTk() {
    throw new UnsupportedOperationException();
  }

  @Override
  public String getBaseClassName() {
    return getClass().getName();
  }
}
