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

import java.util.ArrayList;
import java.util.List;

import de.ivu.document.generator.template.BaseDocument;
import de.ivu.document.generator.template.annotations.DocumentRepeat;
import de.ivu.document.generator.template.annotations.DocumentSimpleField;
import de.ivu.elect.business.ergebnis.control.ErgebnisDaten;
import de.ivu.elect.business.ergebnis.control.ErgebnisDatenReferendumOptionen;
import de.ivu.elect.business.ergebnis.entity.Stimmabgabeart;
import de.ivu.elect.business.gebietsbaum.entity.Wahldurchfuehrungsgebiet;
import de.ivu.elect.business.gruppe.entity.Gruppe;
import de.ivu.elect.business.gruppeimgebiet.entity.GruppeImGebiet;
import de.ivu.elect.business.internet.control.GebietUndStimmabgabeart;
import de.ivu.elect.business.wahlvorschlag.entity.ReferendumOption;
import de.ivu.elect.business.wahlvorschlag.entity.WahlvorschlagStimmzettelPosition;
import de.ivu.elect.dokumente.CoreElectContext;

// Cf. ReferendumVorlageStimmenDocument!!!
public class ReferendumVorlageMitStimmergebnissenDocument extends BaseDocument {

  private static final long serialVersionUID = 1L;

  @DocumentRepeat(value = "ReferendumOptionen", elementClass = ReferendumOptionMitStimmergebnissenDocument.class, itemName = "referendumOption")
  public final List<ReferendumOptionMitStimmergebnissenDocument> referendumOptionen;

  // Stimmzettelposition mit Lücken, z.B. "4"
  @DocumentSimpleField("Position")
  public final Long position;

  @DocumentSimpleField("Position-Formatiert")
  public final String positionFormatted;

  @DocumentSimpleField("Kennzahl-Formatiert")
  public final String kennzahlFormatted;

  @DocumentSimpleField("Position-Fortlaufend")
  public final Long positionFortlaufend;

  @DocumentSimpleField("ReferendumVorlage-Kurzname")
  public final String referendumVorlageKurzname;

  @DocumentSimpleField("ReferendumVorlage-Name")
  public final String referendumVorlageName;

  @DocumentSimpleField("ReferendumVorlage-Schluessel")
  public final String referendumVorlageSchluessel;

  /**
   * @deprecated
   * @see ReferendumVorlageMitStimmergebnissenDocument#referendumVorlageName
   */
  @Deprecated
  @DocumentSimpleField("VorlagenText")
  public final String vorlagenText;

  @DocumentSimpleField("AnzahlGueltigerStimmen")
  public final Long anzahlGueltigerStimmen;

  // ELECT-3760
  @DocumentSimpleField("AnzahlGueltigerStimmen-Urnenwaehler")
  public final Long anzahlGueltigerStimmenUrnenwaehler;

  // ELECT-3760
  @DocumentSimpleField("AnzahlGueltigerStimmen-Briefwaehler")
  public final Long anzahlGueltigerStimmenBriefwaehler;

  @DocumentSimpleField("AnzahlUngueltigerStimmen")
  public final Long anzahlUngueltigerStimmen;

  // ELECT-3760
  @DocumentSimpleField("AnzahlUngueltigerStimmen-Urnenwaehler")
  public final Long anzahlUngueltigerStimmenUrnenwaehler;

  // ELECT-3760
  @DocumentSimpleField("AnzahlUngueltigerStimmen-Briefwaehler")
  public final Long anzahlUngueltigerStimmenBriefwaehler;

  @DocumentSimpleField("AnzahlAbgegebenerStimmen")
  public final Long anzahlAbgegebenerStimmen; // ELECT-6385

  @DocumentSimpleField("AnzahlAbgegebenerStimmen-Urnenwaehler")
  public final Long anzahlAbgegebenerStimmenUrnenwaehler;

  @DocumentSimpleField("AnzahlAbgegebenerStimmen-Briefwaehler")
  public final Long anzahlAbgegebenerStimmenBriefwaehler;

  public ReferendumVorlageMitStimmergebnissenDocument(CoreElectContext coreElectContext, ErgebnisDaten ergebnisDaten, GebietUndStimmabgabeart gebietUndStimmabgabeart,
      GruppeImGebiet referendumVorlageImGebiet, Long laufendeNummer) {
    super();

    Gruppe referendumVorlage = referendumVorlageImGebiet.getGruppe();

    // Cf. AbstractStimmeingabeDocumentFactory#fillInReferendumVorlageStimmenDocument!
    WahlvorschlagStimmzettelPosition referendumVorlageStimmzettelPosition = referendumVorlageImGebiet.getStimmzettelPosition(ergebnisDaten.getEntityAufStimmzettelDaten());

    this.position = referendumVorlageStimmzettelPosition.getPosition();

    this.positionFormatted = referendumVorlageStimmzettelPosition.formatPosition();
    this.kennzahlFormatted = referendumVorlageStimmzettelPosition.formatKennzahl();

    this.positionFortlaufend = laufendeNummer;

    this.referendumOptionen = bestimmeReferendumOptionen(coreElectContext, ergebnisDaten, gebietUndStimmabgabeart, referendumVorlage);

    this.referendumVorlageKurzname = referendumVorlage.getKurzname();
    this.referendumVorlageName = referendumVorlage.getName();
    this.referendumVorlageSchluessel = referendumVorlage.getSchluessel();
    this.vorlagenText = this.referendumVorlageName;

    Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet = gebietUndStimmabgabeart.getWahldurchfuehrungsgebiet();
    ErgebnisDatenReferendumOptionen ergebnisDatenReferendumOptionen = ergebnisDaten.getErgebnisDatenReferendumOptionen();

    long anzahlStimmenGueltig = ergebnisDatenReferendumOptionen.getStimmenFuerReferendumOptionenGueltig(referendumVorlage, gebietUndStimmabgabeart);
    long anzahlStimmenGueltigUrnenwahl = 0L;
    long anzahlStimmenGueltigBriefwahl = 0L;

    long anzahlStimmenUngueltig = ergebnisDatenReferendumOptionen.getStimmenFuerReferendumOptionenUngueltig(referendumVorlage, gebietUndStimmabgabeart);
    long anzahlStimmenUngueltigUrnenwahl = 0L;
    long anzahlStimmenUngueltigBriefwahl = 0L;

    long anzahlStimmenAbgegeben = ergebnisDatenReferendumOptionen.getStimmenFuerReferendumOptionenAbgegeben(referendumVorlage, gebietUndStimmabgabeart);
    long anzahlStimmenAbgegebenUrnenwahl = 0L;
    long anzahlStimmenAbgegebenBriefwahl = 0L;

    for (Wahldurchfuehrungsgebiet erfassungsgebiet : ergebnisDaten.getErfassungsgebiete()) {
      if (erfassungsgebiet.isUntergebietVon(wahldurchfuehrungsgebiet)) {
        Stimmabgabeart stimmabgabeart = Stimmabgabeart.GESAMT; // Gebietsart ist bereits auf Erfassungsgebiet eingeschränkt!

        long anzahlStimmenImErfassungsgebietGueltig = ergebnisDatenReferendumOptionen.getStimmenFuerReferendumOptionenGueltig(referendumVorlage, erfassungsgebiet, stimmabgabeart);
        long anzahlStimmenImErfassungsgebietUngueltig = ergebnisDatenReferendumOptionen.getStimmenFuerReferendumOptionenUngueltig(referendumVorlage, erfassungsgebiet, stimmabgabeart);
        long anzahlStimmenImErfassungsgebietAbgegeben = ergebnisDatenReferendumOptionen.getStimmenFuerReferendumOptionenAbgegeben(referendumVorlage, erfassungsgebiet, stimmabgabeart);

        if (erfassungsgebiet.isUrnenwahlgebiet()) {
          anzahlStimmenGueltigUrnenwahl += anzahlStimmenImErfassungsgebietGueltig;
          anzahlStimmenUngueltigUrnenwahl += anzahlStimmenImErfassungsgebietUngueltig;
          anzahlStimmenAbgegebenUrnenwahl += anzahlStimmenImErfassungsgebietAbgegeben;
        } else {
          anzahlStimmenGueltigBriefwahl += anzahlStimmenImErfassungsgebietGueltig;
          anzahlStimmenUngueltigBriefwahl += anzahlStimmenImErfassungsgebietUngueltig;
          anzahlStimmenAbgegebenBriefwahl += anzahlStimmenImErfassungsgebietAbgegeben;
        }
      }
    }

    this.anzahlGueltigerStimmen = anzahlStimmenGueltig;
    this.anzahlGueltigerStimmenUrnenwaehler = anzahlStimmenGueltigUrnenwahl;
    this.anzahlGueltigerStimmenBriefwaehler = anzahlStimmenGueltigBriefwahl;

    this.anzahlUngueltigerStimmen = anzahlStimmenUngueltig;
    this.anzahlUngueltigerStimmenUrnenwaehler = anzahlStimmenUngueltigUrnenwahl;
    this.anzahlUngueltigerStimmenBriefwaehler = anzahlStimmenUngueltigBriefwahl;

    this.anzahlAbgegebenerStimmen = anzahlStimmenAbgegeben;
    this.anzahlAbgegebenerStimmenUrnenwaehler = anzahlStimmenAbgegebenUrnenwahl;
    this.anzahlAbgegebenerStimmenBriefwaehler = anzahlStimmenAbgegebenBriefwahl;
  }

  private List<ReferendumOptionMitStimmergebnissenDocument> bestimmeReferendumOptionen(CoreElectContext coreElectContext, ErgebnisDaten ergebnisDaten, GebietUndStimmabgabeart gebietUndStimmabgabeart,
      Gruppe referendumVorlage) {
    List<ReferendumOptionMitStimmergebnissenDocument> result = new ArrayList<>();

    for (ReferendumOption referendumOption : ergebnisDaten.getReferendumOptionenSortiertNachPosition(referendumVorlage)) {
      result.add(new ReferendumOptionMitStimmergebnissenDocument(coreElectContext, ergebnisDaten, gebietUndStimmabgabeart, referendumOption));
    }

    return result;
  }
}
