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

import static de.ivu.elect.jee.entity.EntityUtil.castTo;

import java.util.Map;
import java.util.Optional;

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.boundary.WahlverwaltungGebietDescriptor;
import de.ivu.elect.business.gebietsbaum.boundary.WahlverwaltungGebietInformation;
import de.ivu.elect.business.gebietsbaum.entity.Wahldurchfuehrungsgebiet;
import de.ivu.elect.business.gruppe.entity.Gruppe;
import de.ivu.elect.business.internet.control.GebietUndStimmabgabeart;
import de.ivu.elect.business.wahl.entity.WahlartErgebnisart;
import de.ivu.elect.business.wahlvorschlag.entity.ReferendumOption;
import de.ivu.elect.dokumente.ergebnis.AbstractErgebnisTabellarischDocumentZeileCreator;

public class ReferendumErgebnisGesamtergebnisTabellarischDocumentZeileCreator extends AbstractErgebnisTabellarischDocumentZeileCreator<ReferendumErgebnisGesamtergebnisTabellarischDocumentZeile> {

  public ReferendumErgebnisGesamtergebnisTabellarischDocumentZeileCreator() {
    super();
  }

  public ReferendumErgebnisGesamtergebnisTabellarischDocumentZeile createZeile(ErgebnisDaten ergebnisDaten, String erfassungsgebietGebietsreferenzFormat,
      WahlverwaltungGebietInformation stimmzettelgebietInformation, WahlverwaltungGebietInformation gebietUebergeordnetInformation, WahlverwaltungGebietDescriptor erfassungsgebietDescriptor,
      Optional<Gruppe> referendumVorlageIfPresent) {
    Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet = castTo(erfassungsgebietDescriptor.getGebiet(), Wahldurchfuehrungsgebiet.class);

    ReferendumErgebnisGesamtergebnisTabellarischDocumentZeile result = super.createZeile(ergebnisDaten, erfassungsgebietGebietsreferenzFormat, stimmzettelgebietInformation,
        gebietUebergeordnetInformation, erfassungsgebietDescriptor);
    referendumVorlageIfPresent.ifPresent(referendumVorlage -> fillInErgebnisDatenStimmen(result, ergebnisDaten, referendumVorlage, wahldurchfuehrungsgebiet, getStimmabgabeart()));

    return result;
  }

  @Override
  protected ReferendumErgebnisGesamtergebnisTabellarischDocumentZeile createZeile(WahlartErgebnisart ergebnisart, Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet) {
    return new ReferendumErgebnisGesamtergebnisTabellarischDocumentZeile(ergebnisart, wahldurchfuehrungsgebiet);
  }

  @Override
  protected void fillInErgebnisDatenStimmen(ReferendumErgebnisGesamtergebnisTabellarischDocumentZeile zeile, ErgebnisDaten ergebnisDaten, Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet,
      Stimmabgabeart stimmabgabeart) {
    // Cf. ReferendumErgebnisGesamtergebnisTabellarischDocumentZeileCreator#fillInErgebnisDatenStimmen!!!
  }

  private void fillInErgebnisDatenStimmen(ReferendumErgebnisGesamtergebnisTabellarischDocumentZeile zeile, ErgebnisDaten ergebnisDaten, Gruppe referendumVorlage,
      Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet, Stimmabgabeart stimmabgabeart) {
    GebietUndStimmabgabeart gebietUndStimmabgabeart = new GebietUndStimmabgabeart(wahldurchfuehrungsgebiet, stimmabgabeart);

    ErgebnisDatenReferendumOptionen ergebnisDatenReferendumOptionen = ergebnisDaten.getErgebnisDatenReferendumOptionen();
    Map<ReferendumOption, Long> stimmenPerReferendumOption = ergebnisDatenReferendumOptionen.collectStimmenPerReferendumOption(referendumVorlage, gebietUndStimmabgabeart);

    long summeStimmenGueltigIncremented = 0L;

    for (ReferendumOption referendumOption : ergebnisDatenReferendumOptionen.getReferendumOptionenFuerReferendumVorlage(referendumVorlage)) {
      // ELECT-16558
      Long anzahlStimmenGueltig = 0L; // TODO ELECT-16558 = null, wird mit diesem Wert "gerechnet"?

      if (zeile.isAnzahlenVorhanden()) {
        anzahlStimmenGueltig = stimmenPerReferendumOption.getOrDefault(referendumOption, 0L);

        summeStimmenGueltigIncremented += anzahlStimmenGueltig;
      }

      zeile.gueltigeStimmenDerOptionen.add(anzahlStimmenGueltig);
    }

    // ELECT-16558
    Long summeStimmenGesamt = 0L; // TODO ELECT-16558 = null, wird mit diesem Wert "gerechnet"?
    Long summeStimmenGueltig = 0L; // TODO ELECT-16558 = null, wird mit diesem Wert "gerechnet"?
    Long summeStimmenUngueltig = 0L; // TODO ELECT-16558 = null, wird mit diesem Wert "gerechnet"?

    if (zeile.isAnzahlenVorhanden()) {
      summeStimmenGesamt = ergebnisDaten.getErgebnisDatenWaehler().getSummeWaehlerGesamt(wahldurchfuehrungsgebiet, stimmabgabeart);
      summeStimmenGueltig = summeStimmenGueltigIncremented;
      summeStimmenUngueltig = Math.max(0L, summeStimmenGesamt - summeStimmenGueltig);
    }

    zeile.abgegebeneStimmenInsgesamt = summeStimmenGesamt;
    zeile.gueltigeStimmenInsgesamt = summeStimmenGueltig;
    zeile.ungueltigeStimmen = summeStimmenUngueltig;
  }
}
