
package de.ivu.elect.dokumente.stimmeingabe;

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.DocumentSimpleField;
import de.ivu.elect.dokumente.kandidatur.CoreKandidaturDokument;

public class KandidatStimmenDocument extends AbstractStimmenDocument {

  private static final long serialVersionUID = 1L;

  public static final KandidatStimmenDocument EMPTY_OBJECT = new KandidatStimmenDocument(true);

  @DocumentComplexField("Kandidatur")
  public CoreKandidaturDokument kandidatur;

  /**
   * @deprecated
   * @see CoreKandidaturDokument#familienname
   */
  @Deprecated
  @DocumentSimpleField("Familienname")
  public String familienname;

  /**
   * @deprecated
   * @see CoreKandidaturDokument#vorname
   */
  @Deprecated
  @DocumentSimpleField("Vorname")
  public String vorname;

  @DocumentSimpleField("Anzahl-Nennungen")
  public Long anzahlNennungen;

  @DocumentSimpleField("Anzahl-Stimmen-Gesamt")
  public Long anzahlStimmen;

  /**
   * Teilanzahl aller Stimmen der Kandidatur, die gezielt für diese Kandidatur vergeben wurden.
   *
   * @see ELECT-9178
   */
  @DocumentSimpleField("Anteil-Stimmen-Aus-Einzelstimmvergabe")
  public Long anteilStimmenAusEinzelstimmvergabe;

  /**
   * Teilanzahl aller Stimmen der Kandidatur, die sich aus Stimmen für den Wahlvorschlag ergeben, bspw. bei BY die Anzahl der Stimmen aus den "Stimmzetteln mit genau einem unverändert gekennzeichneten
   * Wahlvorschlag" und der Anzahl der Nennungen einer Listenkandidatur.
   *
   * @see ELECT-9178
   */
  @DocumentSimpleField("Anteil-Stimmen-Aus-Wahlvorschlagstimmvergabe")
  public Long anteilStimmenAusWahlvorschlagstimmvergabe;

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

    this.kandidatur = CoreKandidaturDokument.EMPTY_OBJECT;
  }

  public boolean isEmptyObject() {
    return this.equals(EMPTY_OBJECT);
  }

  public void addToDocumentKumuliert(StimmeingabeDocumentContext context, CoreStimmeingabeDocumentBuilder stimmeingabeDocumentBuilder, KandidatStimmenDocument kandidatStimmenDocument) {
    super.addToDocumentKumuliert(context, stimmeingabeDocumentBuilder, kandidatStimmenDocument);

    kandidatStimmenDocument.kandidatur = kandidatur;
    kandidatStimmenDocument.familienname = familienname;
    kandidatStimmenDocument.vorname = vorname;

    kandidatStimmenDocument.anzahlNennungen = anzahlNennungen;

    kandidatStimmenDocument.anzahlStimmen = aggregate(kandidatStimmenDocument.anzahlStimmen, anzahlStimmen);
    kandidatStimmenDocument.anteilStimmenAusWahlvorschlagstimmvergabe = aggregate(kandidatStimmenDocument.anteilStimmenAusWahlvorschlagstimmvergabe, anteilStimmenAusWahlvorschlagstimmvergabe);
    kandidatStimmenDocument.anteilStimmenAusEinzelstimmvergabe = aggregate(kandidatStimmenDocument.anteilStimmenAusEinzelstimmvergabe, anteilStimmenAusEinzelstimmvergabe);
  }

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

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

      if (tk != null) {
        targetPerKey.putIfAbsent(tk, stimmeingabeDocumentBuilder.createKandidatStimmenDocument(context));
        source.addToDocumentKumuliert(context, stimmeingabeDocumentBuilder, targetPerKey.get(tk));
      }
    }

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