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

import java.util.function.Supplier;

import de.ivu.elect.business.gebietsbaum.entity.Gebiet;

public class StimmenWaehler {

  private final Gebiet gebiet;

  private final Supplier<Long> countGesamt;

  private final Supplier<Long> countOhneWahlschein;

  private final Supplier<Long> countMitWahlschein;

  private final Supplier<Long> countMitWahlscheinInUrnenwahlAnzahlAusUrnenwahl;

  private final Supplier<Long> countMitWahlscheinInUrnenwahlAnzahlAusBriefwahl;

  private final Supplier<Long> countMitVollmacht;

  private Long anzahlGesamtErfasst;

  private Long anzahlOhneWahlscheinErfasst;

  private Long anzahlMitWahlscheinErfasst;

  private Long anzahlMitWahlscheinInUrnenwahlAnzahlAusUrnenwahlErfasst;

  private Long anzahlMitWahlscheinInUrnenwahlAnzahlAusBriefwahlErfasst;

  private Long anzahlMitVollmachtErfasst;

  public StimmenWaehler(Gebiet gebiet, Supplier<Long> countGesamt, Supplier<Long> countOhneWahlschein, Supplier<Long> countMitWahlschein,
      Supplier<Long> countMitWahlscheinInUrnenwahlAnzahlAusUrnenwahl, Supplier<Long> countMitWahlscheinInUrnenwahlAnzahlAusBriefwahl, Supplier<Long> countMitVollmacht) {
    super();

    this.gebiet = gebiet;

    this.countGesamt = countGesamt;

    this.countOhneWahlschein = countOhneWahlschein;

    this.countMitWahlschein = countMitWahlschein;
    this.countMitWahlscheinInUrnenwahlAnzahlAusUrnenwahl = countMitWahlscheinInUrnenwahlAnzahlAusUrnenwahl;
    this.countMitWahlscheinInUrnenwahlAnzahlAusBriefwahl = countMitWahlscheinInUrnenwahlAnzahlAusBriefwahl;

    this.countMitVollmacht = countMitVollmacht;

    this.anzahlGesamtErfasst = null;

    this.anzahlOhneWahlscheinErfasst = null;

    this.anzahlMitWahlscheinErfasst = null;
    this.anzahlMitWahlscheinInUrnenwahlAnzahlAusUrnenwahlErfasst = null;
    this.anzahlMitWahlscheinInUrnenwahlAnzahlAusBriefwahlErfasst = null;

    this.anzahlMitVollmachtErfasst = null;
  }

  public long getAnzahlGesamt() {
    long result = getAnzahlGesamtErfasst();

    if (result < 1) {
      result = getAnzahlOhneWahlscheinErfasst() + getAnzahlMitWahlscheinErfasst() + getAnzahlMitVollmachtErfasst();
    }

    return result;
  }

  public long getAnzahlOhneWahlschein() {
    long result = getAnzahlOhneWahlscheinErfasst();

    if (result < 1 && gebiet != null && !gebiet.isBriefwahlgebiet()) {
      result = Math.max(0L, getAnzahlGesamtErfasst() - getAnzahlMitWahlscheinErfasst() - getAnzahlMitVollmachtErfasst());
    }

    return result;
  }

  public long getAnzahlMitWahlschein() {
    long result = getAnzahlMitWahlscheinErfasst();

    if (result < 1 && gebiet != null && gebiet.isBriefwahlgebiet()) {
      result = getAnzahlGesamtErfasst();
    }

    return result;
  }

  public long getAnzahlMitWahlscheinInUrnenwahlAnzahlAusUrnenwahl() {
    long result = getAnzahlMitWahlscheinInUrnenwahlAnzahlAusUrnenwahlErfasst();

    if (result < 1 && gebiet != null && !gebiet.isBriefwahlgebiet()) {
      result = Math.max(0L, getAnzahlMitWahlscheinErfasst() - getAnzahlMitWahlscheinInUrnenwahlAnzahlAusBriefwahlErfasst());
    }

    return result;
  }

  public long getAnzahlMitWahlscheinInUrnenwahlAnzahlAusBriefwahl() {
    return getAnzahlMitWahlscheinInUrnenwahlAnzahlAusBriefwahlErfasst();
  }

  public long getAnzahlMitVollmacht() {
    return getAnzahlMitVollmachtErfasst();
  }

  private long getAnzahlGesamtErfasst() {
    if (anzahlGesamtErfasst == null) {
      anzahlGesamtErfasst = fixNullToZero(countGesamt.get());
    }

    return anzahlGesamtErfasst;
  }

  private long getAnzahlOhneWahlscheinErfasst() {
    if (anzahlOhneWahlscheinErfasst == null) {
      anzahlOhneWahlscheinErfasst = fixNullToZero(countOhneWahlschein.get());
    }

    return anzahlOhneWahlscheinErfasst;
  }

  private long getAnzahlMitWahlscheinErfasst() {
    if (anzahlMitWahlscheinErfasst == null) {
      anzahlMitWahlscheinErfasst = fixNullToZero(countMitWahlschein.get());
    }

    return anzahlMitWahlscheinErfasst;
  }

  private long getAnzahlMitWahlscheinInUrnenwahlAnzahlAusUrnenwahlErfasst() {
    if (anzahlMitWahlscheinInUrnenwahlAnzahlAusUrnenwahlErfasst == null) {
      anzahlMitWahlscheinInUrnenwahlAnzahlAusUrnenwahlErfasst = fixNullToZero(countMitWahlscheinInUrnenwahlAnzahlAusUrnenwahl.get());
    }

    return anzahlMitWahlscheinInUrnenwahlAnzahlAusUrnenwahlErfasst;
  }

  private long getAnzahlMitWahlscheinInUrnenwahlAnzahlAusBriefwahlErfasst() {
    if (anzahlMitWahlscheinInUrnenwahlAnzahlAusBriefwahlErfasst == null) {
      anzahlMitWahlscheinInUrnenwahlAnzahlAusBriefwahlErfasst = fixNullToZero(countMitWahlscheinInUrnenwahlAnzahlAusBriefwahl.get());
    }

    return anzahlMitWahlscheinInUrnenwahlAnzahlAusBriefwahlErfasst;
  }

  private long getAnzahlMitVollmachtErfasst() {
    if (anzahlMitVollmachtErfasst == null) {
      anzahlMitVollmachtErfasst = fixNullToZero(countMitVollmacht.get());
    }

    return anzahlMitVollmachtErfasst;
  }

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

    return value;
  }
}
