
package de.ivu.elect.dokumente.stimmeingabe;

import static java.util.Objects.nonNull;

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

import de.ivu.document.generator.template.annotations.DocumentComplexField;
import de.ivu.document.generator.template.annotations.DocumentRepeat;
import de.ivu.document.generator.template.annotations.DocumentSimpleField;
import de.ivu.elect.dokumente.wahlvorschlag.CoreWahlvorschlagsdatenDocument;

// Cf. ListeMitStimmergebnissenDocument, GebietMitListenDocument, GebietMitDirektkandidatenDocument!!!
public class ListeStimmenDocument extends AbstractStimmenDocument {

  private static final long serialVersionUID = 1L;

  @DocumentComplexField("Wahlvorschlag")
  public CoreWahlvorschlagsdatenDocument wahlvorschlagsdatenDocument;

  @DocumentSimpleField("Stimmen-Gueltig")
  public Long anzahlStimmen;

  @DocumentSimpleField("Stimmen-Gueltig-Nur-Liste")
  public Long anzahlStimmenNurListe;

  @DocumentSimpleField("Stimmen-Gueltig-Nur-Listenkandidaturen")
  public Long anzahlStimmenNurListenkandidaturen;

  /**
   * @see StimmeingabeDocument#stimmzettelWahlvorschlagUnveraendert
   * @see GruppeStimmenDocument#stimmzettelWahlvorschlagUnveraendert
   */
  @DocumentSimpleField("Stimmzettel-Nur-Einzelner-Wahlvorschlag-Unveraendert")
  public Long stimmzettelWahlvorschlagUnveraendert; // ELECT-13791

  /**
   * @see StimmeingabeDocument#stimmzettelWahlvorschlagVeraendert
   * @see GruppeStimmenDocument#stimmzettelWahlvorschlagVeraendert
   */
  @DocumentSimpleField("Stimmzettel-Nur-Einzelner-Wahlvorschlag-Veraendert")
  public Long stimmzettelWahlvorschlagVeraendert; // ELECT-13791

  /**
   * @see StimmeingabeDocument#stimmzettelWahlvorschlagGesamt
   * @see GruppeStimmenDocument#stimmzettelWahlvorschlagGesamt
   */
  @DocumentSimpleField("Stimmzettel-Nur-Einzelner-Wahlvorschlag-Gesamt")
  public Long stimmzettelWahlvorschlagGesamt; // ELECT-13791

  /**
   * @see StimmeingabeDocument#stimmzettelWahlvorschlagPanaschiert
   * @see GruppeStimmenDocument#stimmzettelWahlvorschlagPanaschiert
   */
  @DocumentSimpleField("Stimmzettel-Nur-Einzelner-Wahlvorschlag-Panaschiert")
  public Long stimmzettelWahlvorschlagPanaschiert; // ELECT-13791

  @DocumentRepeat(value = "Listenkandidaturen", elementClass = KandidatStimmenDocument.class, itemName = "listenkandidatur")
  public List<KandidatStimmenDocument> listenkandidaturen;

  public ListeStimmenDocument(boolean eingabenAnzahlenStimmenExcluded) {
    super(eingabenAnzahlenStimmenExcluded);

    this.listenkandidaturen = new ArrayList<>();
  }

  public void addToDocumentKumuliert(StimmeingabeDocumentContext context, CoreStimmeingabeDocumentBuilder stimmeingabeDocumentBuilder, ListeStimmenDocument listeStimmenDocument) {
    super.addToDocumentKumuliert(context, stimmeingabeDocumentBuilder, listeStimmenDocument);

    listeStimmenDocument.wahlvorschlagsdatenDocument = wahlvorschlagsdatenDocument;

    listeStimmenDocument.anzahlStimmen = aggregate(listeStimmenDocument.anzahlStimmen, anzahlStimmen);
    listeStimmenDocument.anzahlStimmenNurListe = aggregate(listeStimmenDocument.anzahlStimmenNurListe, anzahlStimmenNurListe);
    listeStimmenDocument.anzahlStimmenNurListenkandidaturen = aggregate(listeStimmenDocument.anzahlStimmenNurListenkandidaturen, anzahlStimmenNurListenkandidaturen);

    listeStimmenDocument.stimmzettelWahlvorschlagUnveraendert = aggregate(listeStimmenDocument.stimmzettelWahlvorschlagUnveraendert, stimmzettelWahlvorschlagUnveraendert);
    listeStimmenDocument.stimmzettelWahlvorschlagVeraendert = aggregate(listeStimmenDocument.stimmzettelWahlvorschlagVeraendert, stimmzettelWahlvorschlagVeraendert);
    listeStimmenDocument.stimmzettelWahlvorschlagGesamt = aggregate(listeStimmenDocument.stimmzettelWahlvorschlagGesamt, stimmzettelWahlvorschlagGesamt);
    listeStimmenDocument.stimmzettelWahlvorschlagPanaschiert = aggregate(listeStimmenDocument.stimmzettelWahlvorschlagPanaschiert, stimmzettelWahlvorschlagPanaschiert);

    listeStimmenDocument.listenkandidaturen = KandidatStimmenDocument.aggregate(context, stimmeingabeDocumentBuilder, listeStimmenDocument.listenkandidaturen, listenkandidaturen);
  }

  public static List<ListeStimmenDocument> aggregate(StimmeingabeDocumentContext context, CoreStimmeingabeDocumentBuilder stimmeingabeDocumentBuilder, List<ListeStimmenDocument> targets,
      List<ListeStimmenDocument> sources) {
    SortedMap<Object, ListeStimmenDocument> targetPerKey = collectStimmenDocumentToAggregatePerTk(targets);

    for (ListeStimmenDocument source : sources) {
      Object tk = source.getTk();

      if (nonNull(tk)) {
        targetPerKey.putIfAbsent(tk, stimmeingabeDocumentBuilder.createListeStimmenDocument(context));
        source.addToDocumentKumuliert(context, stimmeingabeDocumentBuilder, targetPerKey.get(tk));
      }
    }

    return new ArrayList<>(targetPerKey.values());
  }
}
