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

import de.ivu.elect.business.gebietsbaum.entity.EntityMitGebietVeraenderbar;
import de.ivu.elect.business.gruppe.entity.EntityMitGruppe;
import de.ivu.elect.business.gruppe.entity.Gruppe;
import de.ivu.elect.business.gruppe.entity.SystemGruppe;
import de.ivu.elect.business.gruppe.entity.SystemGruppeEigenschaften;

public abstract class AbstractStimmen extends AbstractMitGruppeUndGebiet implements StimmenBase, EntityMitGruppe<Gruppe>, EntityMitGebietVeraenderbar {

  private static final long serialVersionUID = 1L;

  public AbstractStimmen() {
    super();
  }

  public boolean isGruppeSystemGruppe() {
    return getGruppe().isSystemGruppe();
  }

  public boolean isUebrigeListenstimme(SystemGruppeEigenschaften systemGruppeEigenschaften) {
    return getStimmenart().isListenstimme() && SystemGruppe.UEBRIGE.equalsGruppe(getGruppe(), systemGruppeEigenschaften);
  }

  public boolean isUebrigeDirektstimme(SystemGruppeEigenschaften systemGruppeEigenschaften) {
    return getStimmenart().isDirektstimme() && SystemGruppe.UEBRIGE.equalsGruppe(getGruppe(), systemGruppeEigenschaften);
  }

  public boolean isUebrigeStimme(SystemGruppeEigenschaften systemGruppeEigenschaften) {
    return SystemGruppe.UEBRIGE.equalsGruppe(getGruppe(), systemGruppeEigenschaften);
  }

  public boolean isWahlberechtigte(SystemGruppeEigenschaften systemGruppeEigenschaften) {
    return SystemGruppe.WAHLBERECHTIGTE.equalsGruppe(getGruppe(), systemGruppeEigenschaften);
  }

  public boolean isWaehler(SystemGruppeEigenschaften systemGruppeEigenschaften) {
    return SystemGruppe.WAEHLER.equalsGruppe(getGruppe(), systemGruppeEigenschaften);
  }

  /**
   * @return true <=> eine Stimme eines Kandidaten (gemeint sind explizit NICHT die gueltigen Direktstimmen aka Kopfzahlen)
   */

  public boolean isDirektstimme() {
    return getStimmenart().isDirektstimme() && isPolitischeStimme();
  }

  /**
   * @return true <=> eine Stimme einer Liste (gemeint sind explizit NICHT die gueltigen Listenstimmen aka Kopfzahlen)
   */
  public boolean isListenstimme() {
    return getStimmenart().isListenstimme() && isPolitischeStimme();
  }

  public boolean isListenstimmeAbzuziehen() {
    return getStimmenart().isListenstimmeAbzuziehen() && isPolitischeStimme();
  }

  public boolean isListenstimmeEinzelnerWahlvorschlagUnveraendert() {
    return getStimmenart().isListenstimmeEinzelnerWahlvorschlagUnveraendert() && isPolitischeStimme();
  }

  public boolean isListenstimmeEinzelnerWahlvorschlagVeraendert() {
    return getStimmenart().isListenstimmeEinzelnerWahlvorschlagVeraendert() && isPolitischeStimme();
  }

  public boolean isListenstimmeEinzelnerWahlvorschlagPanaschiert() {
    return getStimmenart().isListenstimmeEinzelnerWahlvorschlagPanaschiert() && isPolitischeStimme();
  }

  public boolean isListenstimmeKeinEinzelnerWahlvorschlagVeraendert() {
    return getStimmenart().isListenstimmeKeinEinzelnerWahlvorschlagVeraendert() && isPolitischeStimme();
  }

  public boolean isListenstimmeKeinEinzelnerWahlvorschlagPanaschiert() {
    return getStimmenart().isListenstimmeKeinEinzelnerWahlvorschlagPanaschiert() && isPolitischeStimme();
  }

  public boolean isListenkandidaturStimme() {
    return getListenkandidatur() != null;
  }

  public boolean isPolitischeStimme() {
    return getGruppe().isPolitischeGruppe();
  }

  /**
   * @return true <=> Systemgruppe und Listenstimmen
   */
  public boolean isGueltigeListenstimme(SystemGruppeEigenschaften systemGruppeEigenschaften) {
    return getStimmenart().isListenstimme() && SystemGruppe.GUELTIGE.equalsGruppe(getGruppe(), systemGruppeEigenschaften);
  }

  public boolean isGueltigeDirektstimme(SystemGruppeEigenschaften systemGruppeEigenschaften) {
    return getStimmenart().isDirektstimme() && SystemGruppe.GUELTIGE.equalsGruppe(getGruppe(), systemGruppeEigenschaften);
  }

  public boolean isUngueltigeListenstimme(SystemGruppeEigenschaften systemGruppeEigenschaften) {
    return getStimmenart().isListenstimme() && SystemGruppe.UNGUELTIGE.equalsGruppe(getGruppe(), systemGruppeEigenschaften);
  }

  public boolean isUngueltigeDirektstimme(SystemGruppeEigenschaften systemGruppeEigenschaften) {
    return getStimmenart().isDirektstimme() && SystemGruppe.UNGUELTIGE.equalsGruppe(getGruppe(), systemGruppeEigenschaften);
  }

  public boolean isReferendumstimme() {
    return getStimmenart().isReferendumStimmenart();
  }

  public void addiere(Long summand) {
    setAnzahl(Math.max(0L, fixNullToZero(getAnzahl()) + fixNullToZero(summand)));
  }

  public void multipliziere(Long multiplikator) {
    setAnzahl(fixNullToZero(getAnzahl()) * fixNullToZero(multiplikator));
  }

  public static long summiere(Iterable<Stimmen> stimmens) {
    long result = 0L;

    for (Stimmen stimmen : stimmens) {
      result += fixNullToZero(stimmen.getAnzahl());
    }

    return result;
  }

  private static long fixNullToZero(Long value) {
    if (value == null) {
      return 0L;
    }

    return value;
  }
}
