
package de.ivu.elect.dokumente.ergebnis.p22;

import java.util.Set;

import de.ivu.document.generator.template.annotations.DocumentMethod;
import de.ivu.document.generator.template.annotations.DocumentParam;
import de.ivu.document.generator.template.annotations.DocumentSimpleField;
import de.ivu.elect.business.gruppe.entity.GruppePK;
import de.ivu.elect.business.gruppe.entity.PolitischeGruppe;
import de.ivu.elect.business.wahlvorschlag.entity.Liste;
import de.ivu.elect.business.wahlvorschlag.entity.NlListe;
import de.ivu.elect.dokumente.ergebnis.NlErgebnisDatenCustomDataDocumentContext;
import de.ivu.elect.dokumente.ergebnis.adapter.Fraction;
import de.ivu.elect.dokumente.ergebnis.adapter.NlErgebnisDaten2ErgebnisDokumentAdapter;
import de.ivu.elect.dokumente.wahlvorschlag.GruppeDokument;

public class P22GruppeDocument extends GruppeDokument {

  private static final long serialVersionUID = 1L;

  @DocumentSimpleField("Ordnungszahl") //Lijstnummer
  public final Long ordnungszahl;

  @DocumentSimpleField("Kennwort") //Lijstname
  public final String kennwort;

  @DocumentSimpleField("RestNachErsterZuteilung") // Overschot
  public final String restNachErsterZuteilung;

  @DocumentSimpleField("RestNachErsterZuteilungGanzzahl")
  public final String restNachErsterZuteilungGanzzahl; // ELECT-11986

  @DocumentSimpleField("RestNachErsterZuteilungBruch")
  public final String restNachErsterZuteilungBruch; // ELECT-11986

  @DocumentSimpleField("AnzahlSitzeAusErsterZuteilung") //volle zetels
  public final Long anzahlSitzeAusErsterZuteilung;

  @DocumentSimpleField("Gesamtzahl-Restsitze-Aus-Oberverteilung-Nach-DHondt") //aantal restzetels
  public final Long anzahlRestsitze;

  @DocumentSimpleField("Anzahl-Restsitze-Aus-Niemeyer-Verteilung-Fuer-Gruppe-In-Oberverteilung") //aantal restzetels
  public final Long anzahlRestSitzeAusNiemeyer;

  @DocumentSimpleField("Gesamtzahl-Sitze-Nach-Niemeyer-Verteilung-Fuer-Gruppe-In-Oberverteilung") //aantal zetels
  public final Long anzahlSitze;

  @DocumentSimpleField("Teilnehmer-An-DHondt-Verteilung-Beschraenkt-Auf-Einen-Sitz-Oberverteilung")
  public final Boolean isTeilnehmerAnDHondtVerteilungBeschraenktAufEinenSitzOberverteilung;

  @DocumentSimpleField("StimmenzahlDerGruppe")
  public final Long stimmenzahlDerGruppe;

  @DocumentSimpleField("StimmenzahlDerGruppeGewichtet")
  public final Long stimmenzahlDerGruppeGewichtetMitVoteValues;

  @DocumentSimpleField("Sitze-Vor-DHondt-Verteilung-Beschraenkt-Auf-Einen-Sitz-Oberverteilung")
  public final Long sitzeVorDHondtVerteilungBeschraenktAufEinenSitzOberverteilung;

  @DocumentSimpleField("Schluessel")
  public final String schluessel;

  @DocumentSimpleField("isEinzelneListe")
  public final Boolean isEinzelneListe;

  @DocumentSimpleField("isGruppeIdentischerListe")
  public final Boolean isGruppeIdentischerListe;

  @DocumentSimpleField("GesamteSitzenzahlDerGruppe")
  public final Long gesamteSitzenzahl;

  private final NlErgebnisDatenCustomDataDocumentContext context;

  private final NlErgebnisDaten2ErgebnisDokumentAdapter adapter;

  private final GruppePK pk;

  private final Set<Liste> listenDerGruppe;

  public P22GruppeDocument(NlErgebnisDatenCustomDataDocumentContext context, NlErgebnisDaten2ErgebnisDokumentAdapter adapter, PolitischeGruppe politischeGruppe, long anzahlSitze, long anzahlStimmen,
      long anzahlStimmenGewichtetMitVoteValues) {
    super(politischeGruppe);

    GruppePK gruppePK = politischeGruppe.getPk();

    this.context = context;
    this.adapter = adapter;

    this.pk = gruppePK;
    this.listenDerGruppe = context.getListen(politischeGruppe);

    this.ordnungszahl = politischeGruppe.getRelativePosition();
    this.kennwort = politischeGruppe.getName();

    this.anzahlSitzeAusErsterZuteilung = adapter.getAnzahlSitzeAusErsterZuteilung(gruppePK);

    Fraction restNachErsterZuteilung = adapter.getRestNachErsterZuteilungFuerGruppeInOberverteilung(gruppePK);
    this.restNachErsterZuteilung = restNachErsterZuteilung.formatGemischterBruch();
    this.restNachErsterZuteilungGanzzahl = anzahlStimmen > 0 ? restNachErsterZuteilung.formatGemischterBruchGanzzahl() : "0"; // ELECT-13661
    this.restNachErsterZuteilungBruch = restNachErsterZuteilung.formatGemischterBruchBruch();

    this.anzahlRestsitze = adapter.getAnzahlRestsitzeAusOberverteilungNachDHondt(gruppePK);
    this.anzahlSitze = adapter.getGesamtzahlSitzeNachNiemeyerVerteilungFuerGruppeInOberverteilung(gruppePK);
    this.anzahlRestSitzeAusNiemeyer = adapter.getAnzahlSitzeAusNiemeyerVerteilungFuerGruppeInOberverteilung(gruppePK);

    this.stimmenzahlDerGruppe = anzahlStimmen;
    this.stimmenzahlDerGruppeGewichtetMitVoteValues = anzahlStimmenGewichtetMitVoteValues;

    boolean teilnehmerAnDHondtVerteilungBeschraenktAufEinenSitzOberverteilung = Boolean.TRUE.equals(adapter.isTeilnehmerAnDHondtVerteilungBeschraenktAufEinenSitzOberverteilung(gruppePK));
    this.isTeilnehmerAnDHondtVerteilungBeschraenktAufEinenSitzOberverteilung = teilnehmerAnDHondtVerteilungBeschraenktAufEinenSitzOberverteilung;

    if (teilnehmerAnDHondtVerteilungBeschraenktAufEinenSitzOberverteilung) {
      this.sitzeVorDHondtVerteilungBeschraenktAufEinenSitzOberverteilung = adapter.getSitzeVorDHondtVerteilungBeschraenktAufEinenSitzOberverteilung(gruppePK);
    } else {
      this.sitzeVorDHondtVerteilungBeschraenktAufEinenSitzOberverteilung = null;
    }

    this.schluessel = politischeGruppe.getSchluessel();

    this.isEinzelneListe = listenDerGruppe.size() == 1;
    this.isGruppeIdentischerListe = !this.isEinzelneListe && this.listenDerGruppe.stream().map(liste -> NlListe.getStelNummerWas(liste).orElse(null)).distinct().count() == 1;

    this.gesamteSitzenzahl = anzahlSitze;
  }

  @DocumentMethod
  public Boolean isGruppeNimmtInGebietTeil(@DocumentParam("wahlkreis") Object value) {
    return listenDerGruppe.stream().anyMatch(liste -> context.existsListeImWahlkreis(liste, value.toString()));
  }

  public Fraction getDHondtQuotientOberverteilung(int laufNullBasiert) {
    return adapter.getDHondtQuotientOberverteilung(pk, laufNullBasiert + 1);
  }

  public Long getAnzahlRestsitzeAusOberverteilungNachDHondt() {
    return adapter.getAnzahlRestsitzeAusOberverteilungNachDHondt(pk);
  }
}
