
package de.ivu.elect.presentation.ergebnis.dokumente.gesamtergebnis;

import static de.ivu.elect.dokumente.DokumentFormatter.formatNumber;

import java.math.BigDecimal;
import java.util.List;
import java.util.Locale;

import javax.annotation.Nullable;

import de.ivu.document.generator.template.BaseDocument;
import de.ivu.document.generator.template.annotations.DocumentSimpleField;
import de.ivu.elect.business.ergebnis.control.AbstractErgebnisDatenWahlberechtigte;
import de.ivu.elect.business.ergebnis.control.ErgebnisDaten;
import de.ivu.elect.business.ergebnis.control.ErgebnisDatenGueltige;
import de.ivu.elect.business.ergebnis.control.ErgebnisDatenStimmzettel;
import de.ivu.elect.business.ergebnis.control.ErgebnisDatenWaehler;
import de.ivu.elect.business.gebietsbaum.entity.Wahldurchfuehrungsgebiet;
import de.ivu.elect.business.internet.control.GebietUndStimmabgabeart;
import de.ivu.elect.dokumente.CoreElectContext;
import de.ivu.elect.presentation.system.PercentUtil;

// ELECT-3760
public class ZwischensummenAufGebietDocument extends BaseDocument {

  private static final long serialVersionUID = 1L;

  @DocumentSimpleField("AnzahlWahlberechtigteOhneWahlschein")
  public final Long anzahlWahlberechtigteOhneWahlschein;

  @DocumentSimpleField("AnzahlWahlberechtigteOhneWahlscheinFormatiert")
  public final String anzahlWahlberechtigteOhneWahlscheinFormatiert;

  @DocumentSimpleField("AnzahlWahlberechtigteMitWahlschein")
  public final Long anzahlWahlberechtigteMitWahlschein;

  @DocumentSimpleField("AnzahlWahlberechtigteMitWahlscheinFormatiert")
  public final String anzahlWahlberechtigteMitWahlscheinFormatiert;

  @DocumentSimpleField("AnzahlWahlberechtigteNichtImWaehlerverzeichnis")
  public final Long anzahlWahlberechtigteNichtImWaehlerverzeichnis;

  @DocumentSimpleField("AnzahlWahlberechtigteNichtImWaehlerverzeichnisFormatiert")
  public final String anzahlWahlberechtigteNichtImWaehlerverzeichnisFormatiert;

  @DocumentSimpleField("AnzahlWahlberechtigteGesamt")
  public final Long anzahlWahlberechtigteGesamt;

  @DocumentSimpleField("AnzahlWahlberechtigteGesamtFormatiert")
  public final String anzahlWahlberechtigteGesamtFormatiert;

  /**
   * @deprecated
   * @see ZwischensummenAufGebietDocument#anzahlWahlberechtigteOhneWahlschein
   */
  @Deprecated
  @DocumentSimpleField("AnzahlWahlberechtigteA1")
  public final Long anzahlWahlberechtigteA1;

  /**
   * @deprecated
   * @see ZwischensummenAufGebietDocument#anzahlWahlberechtigteOhneWahlscheinFormatiert
   */
  @Deprecated
  @DocumentSimpleField("AnzahlWahlberechtigteA1Formatiert")
  public final String anzahlWahlberechtigteA1Formatiert;

  /**
   * @deprecated
   * @see ZwischensummenAufGebietDocument#anzahlWahlberechtigteMitWahlschein
   */
  @Deprecated
  @DocumentSimpleField("AnzahlWahlberechtigteA2")
  public final Long anzahlWahlberechtigteA2;

  /**
   * @deprecated
   * @see ZwischensummenAufGebietDocument#anzahlWahlberechtigteMitWahlscheinFormatiert
   */
  @Deprecated
  @DocumentSimpleField("AnzahlWahlberechtigteA2Formatiert")
  public final String anzahlWahlberechtigteA2Formatiert;

  /**
   * @deprecated
   * @see ZwischensummenAufGebietDocument#anzahlWahlberechtigteNichtImWaehlerverzeichnis
   */
  @Deprecated
  @DocumentSimpleField("AnzahlWahlberechtigteA3")
  public final Long anzahlWahlberechtigteA3;

  /**
   * @deprecated
   * @see ZwischensummenAufGebietDocument#anzahlWahlberechtigteNichtImWaehlerverzeichnisFormatiert
   */
  @Deprecated
  @DocumentSimpleField("AnzahlWahlberechtigteA3Formatiert")
  public final String anzahlWahlberechtigteA3Formatiert;

  /**
   * @deprecated
   * @see ZwischensummenAufGebietDocument#anzahlWahlberechtigteGesamt
   */
  @Deprecated
  @DocumentSimpleField("AnzahlWahlberechtigteA1A2")
  public final Long anzahlWahlberechtigteA1A2;

  /**
   * @deprecated
   * @see ZwischensummenAufGebietDocument#anzahlWahlberechtigteGesamtFormatiert
   */
  @Deprecated
  @DocumentSimpleField("AnzahlWahlberechtigteA1A2Formatiert")
  public final String anzahlWahlberechtigteA1A2Formatiert;

  @DocumentSimpleField("AnzahlWählerOhneWahlschein")
  public final Long anzahlWaehlerOhneWahlschein;

  @DocumentSimpleField("AnzahlWählerOhneWahlscheinFormatiert")
  public final String anzahlWaehlerOhneWahlscheinFormatiert;

  @DocumentSimpleField("AnzahlWählerMitWahlschein")
  public final Long anzahlWaehlerMitWahlschein;

  @DocumentSimpleField("AnzahlWählerMitWahlscheinFormatiert")
  public final String anzahlWaehlerMitWahlscheinFormatiert;

  @DocumentSimpleField("AnzahlWählerMitWahlscheinAnteilAusUrnenwahl")
  public final Long anzahlWaehlerMitWahlscheinAnteilAusUrnenwahl;

  @DocumentSimpleField("AnzahlWählerMitWahlscheinAnteilAusUrnenwahlFormatiert")
  public final String anzahlWaehlerMitWahlscheinAnteilAusUrnenwahlFormatiert;

  @DocumentSimpleField("AnzahlWählerMitWahlscheinAnteilAusBriefwahl")
  public final Long anzahlWaehlerMitWahlscheinAnteilAusBriefwahl;

  @DocumentSimpleField("AnzahlWählerMitWahlscheinAnteilAusBriefwahlFormatiert")
  public final String anzahlWaehlerMitWahlscheinAnteilAusBriefwahlFormatiert;

  @DocumentSimpleField("AnzahlWählerGesamt")
  public final Long anzahlWaehlerGesamt;

  @DocumentSimpleField("AnzahlWählerGesamtFormatiert")
  public final String anzahlWaehlerGesamtFormatiert;

  @DocumentSimpleField("AnzahlWählerGesamtAnteil")
  public final BigDecimal waehlerGesamtProzent;

  @DocumentSimpleField("AnzahlDirektstimmenGültig")
  public final Long anzahlGueltigeDirektstimmen;

  @DocumentSimpleField("AnzahlDirektstimmenGültigFormatiert")
  public final String anzahlGueltigeDirektstimmenFormatiert;

  @DocumentSimpleField("AnzahlDirektstimmenUngültig")
  public final Long anzahlUngueltigeDirektstimmen;

  @DocumentSimpleField("AnzahlDirektstimmenUngültigFormatiert")
  public final String anzahlUngueltigeDirektstimmenFormatiert;

  @DocumentSimpleField("AnzahlDirektstimmenGesamt")
  public final Long anzahlGesamtDirektstimmen;

  @DocumentSimpleField("AnzahlDirektstimmenGesamtFormatiert")
  public final String anzahlGesamtDirektstimmenFormatiert;

  @DocumentSimpleField("AnzahlListenstimmenGültig")
  public final Long anzahlGueltigeListenstimmen;

  @DocumentSimpleField("AnzahlListenstimmenGültigFormatiert")
  public final String anzahlGueltigeListenstimmenFormatiert;

  @DocumentSimpleField("AnzahlListenstimmenUngültig")
  public final Long anzahlUngueltigeListenstimmen;

  @DocumentSimpleField("AnzahlListenstimmenUngültigFormatiert")
  public final String anzahlUngueltigeListenstimmenFormatiert;

  @DocumentSimpleField("AnzahlListenstimmenGesamt")
  public final Long anzahlGesamtListenstimmen;

  @DocumentSimpleField("AnzahlListenstimmenGesamtFormatiert")
  public final String anzahlGesamtListenstimmenFormatiert;

  @DocumentSimpleField("AnzahlStimmzettelGültig")
  public final Long anzahlGueltigeStimmzettel;

  @DocumentSimpleField("AnzahlStimmzettelGültigFormatiert")
  public final String anzahlGueltigeStimmzettelFormatiert;

  @DocumentSimpleField("AnzahlStimmzettelUngültig")
  public final Long anzahlUngueltigeStimmzettel;

  @DocumentSimpleField("AnzahlStimmzettelUngültigFormatiert")
  public final String anzahlUngueltigeStimmzettelFormatiert;

  @DocumentSimpleField("AnzahlStimmzettelGesamt")
  public final Long anzahlGesamtStimmzettel;

  @DocumentSimpleField("AnzahlStimmzettelGesamtFormatiert")
  public final String anzahlGesamtStimmzettelFormatiert;

  public ZwischensummenAufGebietDocument(CoreElectContext coreElectContext, ErgebnisDaten ergebnisDaten, GebietUndStimmabgabeart gebietUebergeordnetUndStimmabgabeart,
      List<Wahldurchfuehrungsgebiet> erfassungsgebieteUntergeordnet) {
    super();

    AbstractErgebnisDatenWahlberechtigte ergebnisDatenWahlberechtigte = ergebnisDaten.getErgebnisDatenWahlberechtigte();
    ErgebnisDatenWaehler ergebnisDatenWaehler = ergebnisDaten.getErgebnisDatenWaehler();
    ErgebnisDatenGueltige ergebnisDatenGueltige = ergebnisDaten.getErgebnisDatenGueltige();
    ErgebnisDatenStimmzettel ergebnisDatenStimmzettel = ergebnisDaten.getErgebnisDatenStimmzettel();

    Long anzahlWaehlerGesamtGebietUebergeordnet = ergebnisDatenWaehler.getSummeWaehlerGesamt(gebietUebergeordnetUndStimmabgabeart); // ELECT-4246

    Long summeWahlberechtigteOhneWahlschein = 0L;
    Long summeWahlberechtigteMitWahlschein = 0L;
    Long summeWahlberechtigteNichtImWaehlerverzeichnis = 0L;
    Long summeWahlberechtigteGesamt = 0L;

    Long summeWaehlerOhneWahlschein = 0L;
    Long summeWaehlerMitWahlschein = 0L;
    Long summeWaehlerMitWahlscheinInUrnenwahlAnzahlAusUrnenwahl = 0L;
    Long summeWaehlerMitWahlscheinInUrnenwahlAnzahlAusBriefwahl = 0L;
    Long summeWaehlerGesamt = 0L;

    Long summeDirektstimmenGueltig = 0L;
    Long summeDirektstimmenUngueltig = 0L;
    Long summeDirektstimmenGesamt = 0L;

    Long summeListenstimmenGueltig = 0L;
    Long summeListenstimmenUngueltig = 0L;
    Long summeListenstimmenGesamt = 0L;

    Long summeStimmzettelGueltig = 0L;
    Long summeStimmzettelUngueltig = 0L;
    Long summeStimmzettelGesamt = 0L;

    for (Wahldurchfuehrungsgebiet erfassungsgebiet : erfassungsgebieteUntergeordnet) {
      GebietUndStimmabgabeart erfassungsgebietUndStimmabgabeart = new GebietUndStimmabgabeart(erfassungsgebiet, gebietUebergeordnetUndStimmabgabeart.getStimmabgabeart());

      summeWahlberechtigteOhneWahlschein = sum(summeWahlberechtigteOhneWahlschein, ergebnisDatenWahlberechtigte.getSummeWahlberechtigteOhneWahlschein(erfassungsgebietUndStimmabgabeart));
      summeWahlberechtigteMitWahlschein = sum(summeWahlberechtigteMitWahlschein, ergebnisDatenWahlberechtigte.getSummeWahlberechtigteMitWahlschein(erfassungsgebietUndStimmabgabeart));
      summeWahlberechtigteNichtImWaehlerverzeichnis = sum(summeWahlberechtigteNichtImWaehlerverzeichnis,
          ergebnisDatenWahlberechtigte.getSummeWahlberechtigteNichtImWaehlerverzeichnis(erfassungsgebietUndStimmabgabeart));
      summeWahlberechtigteGesamt = sum(summeWahlberechtigteGesamt, ergebnisDatenWahlberechtigte.getSummeWahlberechtigteGesamt(erfassungsgebietUndStimmabgabeart));

      summeWaehlerOhneWahlschein = sum(summeWaehlerOhneWahlschein, ergebnisDatenWaehler.getSummeWaehlerOhneWahlschein(erfassungsgebietUndStimmabgabeart));
      summeWaehlerMitWahlschein = sum(summeWaehlerMitWahlschein, ergebnisDatenWaehler.getSummeWaehlerMitWahlschein(erfassungsgebietUndStimmabgabeart));
      summeWaehlerMitWahlscheinInUrnenwahlAnzahlAusUrnenwahl = sum(summeWaehlerMitWahlscheinInUrnenwahlAnzahlAusUrnenwahl,
          ergebnisDatenWaehler.getSummeWaehlerMitWahlscheinInUrnenwahlAnzahlAusUrnenwahl(erfassungsgebietUndStimmabgabeart));
      summeWaehlerMitWahlscheinInUrnenwahlAnzahlAusBriefwahl = sum(summeWaehlerMitWahlscheinInUrnenwahlAnzahlAusBriefwahl,
          ergebnisDatenWaehler.getSummeWaehlerMitWahlscheinInUrnenwahlAnzahlAusBriefwahl(erfassungsgebietUndStimmabgabeart));
      summeWaehlerGesamt = sum(summeWaehlerGesamt, ergebnisDatenWaehler.getSummeWaehlerGesamt(erfassungsgebietUndStimmabgabeart));

      summeDirektstimmenGueltig = sum(summeDirektstimmenGueltig, ergebnisDatenGueltige.getErststimmenAktuellGueltig(erfassungsgebietUndStimmabgabeart));
      summeDirektstimmenUngueltig = sum(summeDirektstimmenUngueltig, ergebnisDatenGueltige.getErststimmenAktuellUngueltig(erfassungsgebietUndStimmabgabeart));
      summeDirektstimmenGesamt = sum(summeDirektstimmenGesamt, ergebnisDatenGueltige.getErststimmenAktuellGesamt(erfassungsgebietUndStimmabgabeart));

      summeListenstimmenGueltig = sum(summeListenstimmenGueltig, ergebnisDatenGueltige.getZweitstimmenAktuellGueltig(erfassungsgebietUndStimmabgabeart));
      summeListenstimmenUngueltig = sum(summeListenstimmenUngueltig, ergebnisDatenGueltige.getZweitstimmenAktuellUngueltig(erfassungsgebietUndStimmabgabeart));
      summeListenstimmenGesamt = sum(summeListenstimmenGesamt, ergebnisDatenGueltige.getZweitstimmenAktuellGesamt(erfassungsgebietUndStimmabgabeart));

      summeStimmzettelGueltig = sum(summeStimmzettelGueltig, ergebnisDatenStimmzettel.getStimmzettelAktuellGueltig(erfassungsgebietUndStimmabgabeart));
      summeStimmzettelUngueltig = sum(summeStimmzettelUngueltig, ergebnisDatenStimmzettel.getStimmzettelAktuellUngueltig(erfassungsgebietUndStimmabgabeart));
      summeStimmzettelGesamt = sum(summeStimmzettelGesamt, ergebnisDatenStimmzettel.getStimmzettelAktuellGesamt(erfassungsgebietUndStimmabgabeart));
    }

    Locale locale = coreElectContext.getLocale();

    this.anzahlWahlberechtigteOhneWahlschein = summeWahlberechtigteOhneWahlschein;
    this.anzahlWahlberechtigteOhneWahlscheinFormatiert = formatNumber(summeWahlberechtigteOhneWahlschein, locale);
    this.anzahlWahlberechtigteMitWahlschein = summeWahlberechtigteMitWahlschein;
    this.anzahlWahlberechtigteMitWahlscheinFormatiert = formatNumber(summeWahlberechtigteMitWahlschein, locale);
    this.anzahlWahlberechtigteNichtImWaehlerverzeichnis = summeWahlberechtigteNichtImWaehlerverzeichnis;
    this.anzahlWahlberechtigteNichtImWaehlerverzeichnisFormatiert = formatNumber(summeWahlberechtigteNichtImWaehlerverzeichnis, locale);
    this.anzahlWahlberechtigteGesamt = summeWahlberechtigteGesamt;
    this.anzahlWahlberechtigteGesamtFormatiert = formatNumber(summeWahlberechtigteGesamt, locale);

    // LEGACY!!!
    this.anzahlWahlberechtigteA1 = this.anzahlWahlberechtigteOhneWahlschein;
    this.anzahlWahlberechtigteA1Formatiert = this.anzahlWahlberechtigteOhneWahlscheinFormatiert;
    this.anzahlWahlberechtigteA2 = this.anzahlWahlberechtigteMitWahlschein;
    this.anzahlWahlberechtigteA2Formatiert = this.anzahlWahlberechtigteMitWahlscheinFormatiert;
    this.anzahlWahlberechtigteA3 = this.anzahlWahlberechtigteNichtImWaehlerverzeichnis;
    this.anzahlWahlberechtigteA3Formatiert = this.anzahlWahlberechtigteNichtImWaehlerverzeichnisFormatiert;
    this.anzahlWahlberechtigteA1A2 = sum(summeWahlberechtigteOhneWahlschein, summeWahlberechtigteMitWahlschein);
    this.anzahlWahlberechtigteA1A2Formatiert = formatNumber(this.anzahlWahlberechtigteA1A2, locale);

    this.anzahlWaehlerOhneWahlschein = summeWaehlerOhneWahlschein;
    this.anzahlWaehlerOhneWahlscheinFormatiert = formatNumber(summeWaehlerOhneWahlschein, locale);
    this.anzahlWaehlerMitWahlschein = summeWaehlerMitWahlschein;
    this.anzahlWaehlerMitWahlscheinFormatiert = formatNumber(summeWaehlerMitWahlschein, locale);
    this.anzahlWaehlerMitWahlscheinAnteilAusUrnenwahl = summeWaehlerMitWahlscheinInUrnenwahlAnzahlAusUrnenwahl;
    this.anzahlWaehlerMitWahlscheinAnteilAusUrnenwahlFormatiert = formatNumber(summeWaehlerMitWahlscheinInUrnenwahlAnzahlAusUrnenwahl, locale);
    this.anzahlWaehlerMitWahlscheinAnteilAusBriefwahl = summeWaehlerMitWahlscheinInUrnenwahlAnzahlAusBriefwahl;
    this.anzahlWaehlerMitWahlscheinAnteilAusBriefwahlFormatiert = formatNumber(summeWaehlerMitWahlscheinInUrnenwahlAnzahlAusBriefwahl, locale);
    this.anzahlWaehlerGesamt = summeWaehlerGesamt;
    this.anzahlWaehlerGesamtFormatiert = formatNumber(summeWaehlerGesamt, locale);
    this.waehlerGesamtProzent = PercentUtil.percent(anzahlWaehlerGesamtGebietUebergeordnet, summeWaehlerGesamt); // ELECT-4246 Interessant für Berliner Wahlbuch...

    this.anzahlGueltigeDirektstimmen = summeDirektstimmenGueltig;
    this.anzahlGueltigeDirektstimmenFormatiert = formatNumber(summeDirektstimmenGueltig, locale);
    this.anzahlUngueltigeDirektstimmen = summeDirektstimmenUngueltig;
    this.anzahlUngueltigeDirektstimmenFormatiert = formatNumber(summeDirektstimmenUngueltig, locale);
    this.anzahlGesamtDirektstimmen = summeDirektstimmenGesamt;
    this.anzahlGesamtDirektstimmenFormatiert = formatNumber(summeDirektstimmenGesamt, locale);

    this.anzahlGueltigeListenstimmen = summeListenstimmenGueltig;
    this.anzahlGueltigeListenstimmenFormatiert = formatNumber(summeListenstimmenGueltig, locale);
    this.anzahlUngueltigeListenstimmen = summeListenstimmenUngueltig;
    this.anzahlUngueltigeListenstimmenFormatiert = formatNumber(summeListenstimmenUngueltig, locale);
    this.anzahlGesamtListenstimmen = summeListenstimmenGesamt;
    this.anzahlGesamtListenstimmenFormatiert = formatNumber(summeListenstimmenGesamt, locale);

    this.anzahlGueltigeStimmzettel = summeStimmzettelGueltig;
    this.anzahlGueltigeStimmzettelFormatiert = formatNumber(summeStimmzettelGueltig, locale);
    this.anzahlUngueltigeStimmzettel = summeStimmzettelUngueltig;
    this.anzahlUngueltigeStimmzettelFormatiert = formatNumber(summeStimmzettelUngueltig, locale);
    this.anzahlGesamtStimmzettel = summeStimmzettelGesamt;
    this.anzahlGesamtStimmzettelFormatiert = formatNumber(summeStimmzettelGesamt, locale);
  }

  private Long sum(@Nullable Long one, @Nullable Long another) {
    return sumOrDefault(one, another, 0L);
  }

  private Long sumOrDefault(@Nullable Long one, @Nullable Long another, Long defaultValue) {
    if (one == null && another == null) {
      return defaultValue;
    }

    if (one == null) {
      return another;
    }

    if (another == null) {
      return one;
    }

    return one + another;
  }
}
