
package de.ivu.elect.business.stimmeingabe.control.fiktive;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import de.ivu.elect.business.gruppe.entity.Gruppe;
import de.ivu.elect.business.hochrechnung.entity.AnzahlStimmenProWaehlerNachStimmenartBestimmer;
import de.ivu.elect.business.hochrechnung.entity.GebietDaten;
import de.ivu.elect.business.hochrechnung.entity.ReferendumFrage;
import de.ivu.elect.business.hochrechnung.entity.StimmenhochrechnerGebietAusgabedaten;
import de.ivu.elect.business.stimmeingabe.entity.Ergebniseingang;
import de.ivu.elect.business.stimmeingabe.entity.Stimmeingabe;
import de.ivu.elect.business.stimmeingabe.entity.StimmeingabeReferendumOptionStimmen;
import de.ivu.elect.business.stimmeingabe.entity.StimmeingabeReferendumVorlageStimmen;
import de.ivu.elect.business.stimmeingabe.entity.StimmeingabeReferendumVorlageStimmenErfassenModel;
import de.ivu.elect.business.wahlvorschlag.entity.ReferendumOption;

public class ReferendumOptionStimmeingabenAusFiktivwertenSetzer extends AbstractStimmeingabenAusFiktivwertenSetzer {

  public static final String COMPONENT_NAME = "referendumOptionStimmeingabenAusFiktivwertenSetzer";

  @Override
  public boolean isVomLetztenErgebniseingangUebernommeneStimmenZuUeberschreiben(Ergebniseingang ergebniseingangAktuell, Collection<Stimmeingabe> uebernommeneStimmeingaben) {
    if (ergebniseingangAktuell.isErgebniseingangsartVorlaeufig()) {
      return true; // Vorlaeufiger Ergebniseingang kann ueberschrieben werden
    }

    // ueberschreibe, wenn es dann keine echt positive Zahlen vorhanden sind.
    return uebernommeneStimmeingaben.stream().noneMatch(stimmeingabe -> stimmeingabe != null && stimmeingabe.hasAnzahlGroesserNull());
  }

  @Override
  public void setzeErgebniseingangStimmeingabenAnzahlAusHochgerechnetenWerten(Ergebniseingang ergebniseingang, StimmenhochrechnerGebietAusgabedaten hochrechnerAusgabedaten, AnzahlStimmenProWaehlerNachStimmenartBestimmer anzahlStimmenProWaehlerBestimmer) {
    if (hochrechnerAusgabedaten == null) {
      return;
    }
    GebietDaten<Long> hochgerechnetAlsAnzahlen = hochrechnerAusgabedaten.getHochgerechnetAlsAnzahlen(anzahlStimmenProWaehlerBestimmer);
    if (hochgerechnetAlsAnzahlen == null) {
      return;
    }

    StimmeingabeReferendumVorlageStimmenErfassenModel stimmeingabeReferendumVorlageStimmenErfassenModel = ergebniseingang
        .getStimmeingabeReferendumVorlageStimmenErfassenModel();
    if (stimmeingabeReferendumVorlageStimmenErfassenModel == null) {
      return;
    }

    stimmeingabeReferendumVorlageStimmenErfassenModel.getStimmenReferendumVorlage().forEach(
        stimmeingabeReferendumVorlageStimmen -> {
          fuelleStimmeingabeReferendumVorlageStimmenAusHochgerechnetenWerten(ergebniseingang, stimmeingabeReferendumVorlageStimmen, hochgerechnetAlsAnzahlen);
        }
    );
  }

  private void fuelleStimmeingabeReferendumVorlageStimmenAusHochgerechnetenWerten(Ergebniseingang ergebniseingang, StimmeingabeReferendumVorlageStimmen stimmeingabeReferendumVorlageStimmen, GebietDaten<Long> hochgerechnetAlsAnzahlen) {
    if (stimmeingabeReferendumVorlageStimmen == null) {
      return;
    }
    Gruppe referendumVorlage = stimmeingabeReferendumVorlageStimmen.getGruppe();
    if (referendumVorlage == null || hochgerechnetAlsAnzahlen == null) {
      return;
    }
    ReferendumFrage<Long> referendumFrageHochgerechnet = hochgerechnetAlsAnzahlen.getReferendumFragen().get(referendumVorlage);
    fuelleStimmeingabeReferendumOptionenStimmenAusHochgerechneterReferendumFrage(ergebniseingang, stimmeingabeReferendumVorlageStimmen.getStimmeingabeReferendumOptionStimmen(), referendumFrageHochgerechnet);
  }

  private void fuelleStimmeingabeReferendumOptionenStimmenAusHochgerechneterReferendumFrage(Ergebniseingang ergebniseingang, List<StimmeingabeReferendumOptionStimmen> stimmeingabeReferendumOptionStimmen, ReferendumFrage<Long> referendumFrageHochgerechnet) {
    List<Stimmeingabe> stimmeingaben = new ArrayList<>();
    stimmeingabeReferendumOptionStimmen.forEach(stimmeingabeReferendumOptionStimme -> stimmeingaben.add(stimmeingabeReferendumOptionStimme.getStimmeingabe()));
    if (!isVomLetztenErgebniseingangUebernommeneStimmenZuUeberschreiben(ergebniseingang, stimmeingaben)) {
      return;
    }
    stimmeingabeReferendumOptionStimmen.forEach(stimmeingabeReferendumOptionStimme -> {
      fuelleStimmeingabeReferendumOptionStimmeAusHochgerechneterReferendumFrage(stimmeingabeReferendumOptionStimme, referendumFrageHochgerechnet);
        }
    );
  }

  private void fuelleStimmeingabeReferendumOptionStimmeAusHochgerechneterReferendumFrage(StimmeingabeReferendumOptionStimmen stimmeingabeReferendumOptionStimme, ReferendumFrage<Long> referendumFrageHochgerechnet) {
    ReferendumOption referendumOption = stimmeingabeReferendumOptionStimme.getReferendumOption();
    if (referendumOption != null) {
      fuelleReferendumOptionStimmeAusHochgerechneterReferendumFrage(referendumOption, stimmeingabeReferendumOptionStimme, referendumFrageHochgerechnet);
    } else {
      fuelleZwischensummeAnzahlAusHochgerechneterReferendumFrage(stimmeingabeReferendumOptionStimme, referendumFrageHochgerechnet);
    }

  }

  private void fuelleZwischensummeAnzahlAusHochgerechneterReferendumFrage(StimmeingabeReferendumOptionStimmen stimmeingabeReferendumOptionStimme, ReferendumFrage<Long> referendumFrageHochgerechnet) {
    Stimmeingabe stimmeingabe = stimmeingabeReferendumOptionStimme.getStimmeingabe();

    if (stimmeingabeReferendumOptionStimme.isStimmeingabeZwischensummeAnzahlGueltigeGesamt()) {
      setzeStimmenEingabeAnzahl(referendumFrageHochgerechnet.getGueltige(), stimmeingabe);
    }

    else if (stimmeingabeReferendumOptionStimme.isStimmeingabeZwischensummeAnzahlUngueltigeGesamt()) {
      setzeStimmenEingabeAnzahl(referendumFrageHochgerechnet.getUngueltige(), stimmeingabe);
    }
  }

  private void fuelleReferendumOptionStimmeAusHochgerechneterReferendumFrage(ReferendumOption referendumOption, StimmeingabeReferendumOptionStimmen stimmeingabeReferendumOptionStimme, ReferendumFrage<Long> referendumFrageHochgerechnet) {
    if (referendumOption == null || referendumFrageHochgerechnet.getStimmenPerReferendumOption() == null) {
      return;
    }
    Long anzahl = referendumFrageHochgerechnet.getStimmenPerReferendumOption().get(referendumOption);
    setzeStimmenEingabeAnzahl(anzahl, stimmeingabeReferendumOptionStimme.getStimmeingabe());
  }
}
