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

import static java.util.Arrays.asList;
import static java.util.stream.Collectors.toList;

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

import de.ivu.elect.business.stimmeingabe.entity.AbstractStimmeingabe;
import de.ivu.elect.business.stimmeingabe.entity.Stimmeingabe;
import de.ivu.elect.business.stimmeingabe.entity.StimmeingabePlausiKonfiguration;
import de.ivu.elect.jee.faces.Messages;

/*
 * BEI ANPASSUNGEN AUCH AbstractMucStimmeingabeAnzahlComparedToStimmeingabeAnzahlenSummePlausi ANPASSEN!!!
 */
public abstract class AbstractStimmeingabeAnzahlComparedToStimmeingabeAnzahlenSummePlausi extends AbstractStimmeingabeAnzahlComparedToPlausi {

  private final Collection<Stimmeingabe> comparedToStimmeingaben;

  protected AbstractStimmeingabeAnzahlComparedToStimmeingabeAnzahlenSummePlausi(AbstractStimmeingabeAnzahlComparedToPlausiDefinition stimmeingabeAnzahlComparedToPlausiDefinition,
      Stimmeingabe comparedToStimmeingabe, StimmeingabePlausiKonfiguration stimmeingabePlausiKonfiguration, Messages messages) {
    this(stimmeingabeAnzahlComparedToPlausiDefinition, asList(comparedToStimmeingabe), stimmeingabePlausiKonfiguration, messages);
  }

  protected AbstractStimmeingabeAnzahlComparedToStimmeingabeAnzahlenSummePlausi(AbstractStimmeingabeAnzahlComparedToPlausiDefinition stimmeingabeAnzahlComparedToPlausiDefinition,
      Collection<Stimmeingabe> comparedToStimmeingaben, StimmeingabePlausiKonfiguration stimmeingabePlausiKonfiguration, Messages messages) {
    super(stimmeingabeAnzahlComparedToPlausiDefinition, stimmeingabePlausiKonfiguration, messages);

    this.comparedToStimmeingaben = comparedToStimmeingaben.stream().filter(Objects::nonNull).collect(toList());
  }

  @Override
  protected boolean isPlausibilisierenZulaessig(Stimmeingabe stimmeingabe) {
    return super.isPlausibilisierenZulaessig(stimmeingabe) && !getComparedToStimmeingaben().isEmpty() && (stimmeingabe.hasAnzahlGroesserGleichNull() || getComparedToValue() > 0);
  }

  @Override
  protected StimmeingabePlausiResult createPlausiResult(Stimmeingabe stimmeingabe) {
    Double anzahlSoll = calculateComparedToValue();
    Double anzahlSollDifferenz = anzahlSoll - calculateStimmeingabeAnzahl(stimmeingabe);

    return createPlausiResult(stimmeingabe, anzahlSoll, anzahlSollDifferenz, getFiktiveWerteFehlerBeheber());
  }

  @Override
  protected Long getComparedToValue() {
    return getComparedToStimmeingabenHavingAnzahlGroesserGleichNull().stream() //
        .mapToLong(AbstractStimmeingabe::getAnzahl) //
        .sum();
  }

  protected Collection<Stimmeingabe> getComparedToStimmeingabenHavingAnzahlGroesserGleichNull() {
    return getComparedToStimmeingaben().stream() //
        .filter(Stimmeingabe::hasAnzahlGroesserGleichNull) //
        .collect(toList());
  }

  protected Collection<Stimmeingabe> getComparedToStimmeingaben() {
    return comparedToStimmeingaben;
  }

  @Override
  protected List<Object> getStimmeingabefehlerBeschreibungParameters(Stimmeingabe stimmeingabe) {
    List<Object> result = new ArrayList<>(super.getStimmeingabefehlerBeschreibungParameters(stimmeingabe));

    Long comparedToStimmeingabenAnzahlenSumme = getComparedToValue();

    if (comparedToStimmeingabenAnzahlenSumme == null || comparedToStimmeingabenAnzahlenSumme < 1L) {
      comparedToStimmeingabenAnzahlenSumme = 0L;
    }

    result.add(comparedToStimmeingabenAnzahlenSumme); // ELECTDD-583

    return result;
  }
}
