
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.control.StimmenPool;
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) {
    StimmenPool stimmen = ergebnisDaten.getStimmen();

    ErgebnisDatenReferendumOptionen ergebnisDatenReferendumOptionen = ergebnisDaten.getErgebnisDatenReferendumOptionen();
    Map<ReferendumOption, Long> stimmenPerReferendumOption = ergebnisDatenReferendumOptionen.collectStimmenPerReferendumOption(referendumVorlage,
        new GebietUndStimmabgabeart(wahldurchfuehrungsgebiet, stimmabgabeart));

    long summeStimmenGueltig = 0;

    for (ReferendumOption referendumOption : ergebnisDatenReferendumOptionen.getReferendumOptionenFuerReferendumVorlage(referendumVorlage)) {
      Long anzahlStimmenGueltig = stimmenPerReferendumOption.get(referendumOption);

      zeile.gueltigeStimmenDerOptionen.add(anzahlStimmenGueltig);

      summeStimmenGueltig += anzahlStimmenGueltig;
    }

    Long summeStimmenGesamt = ergebnisDaten.getErgebnisDatenWaehler().getSummeWaehlerGesamt(wahldurchfuehrungsgebiet, stimmabgabeart);

    zeile.gueltigeStimmenInsgesamt = summeStimmenGueltig;
    zeile.abgegebeneStimmenInsgesamt = summeStimmenGesamt;
    zeile.ungueltigeStimmen = Math.max(0L, summeStimmenGesamt - summeStimmenGueltig);
  }
}
