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

import static de.ivu.elect.business.ElectSystemProperties.PLAUSI_BUILDER_LOG_STIMMEINGABE_PLAUSIS_ENABLED;
import static java.util.Objects.nonNull;
import static java.util.stream.Collectors.toSet;

import java.util.Collection;
import java.util.HashSet;
import java.util.Objects;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import de.ivu.elect.business.stimmeingabe.control.plausi.AbstractPlausiBuilder;
import de.ivu.elect.business.stimmeingabe.control.plausi.StimmeingabePlausi;
import de.ivu.elect.business.stimmeingabe.control.plausi.StimmeingabePlausiBuilderContext;
import de.ivu.elect.business.stimmeingabe.entity.Ergebniseingang;
import de.ivu.elect.business.stimmeingabe.entity.Stimmeingabe;

public interface PlausiBuilder {

  Logger LOG = LoggerFactory.getLogger(AbstractPlausiBuilder.class);

  // ELECT-6549, Quick-Fix um alle angewandten Plausis zu ermitteln. Besser wäre eine Enum o.Ä. ...
  boolean LOG_STIMMEINGABE_PLAUSIS_ENABLED = "true".equals(System.getProperty(PLAUSI_BUILDER_LOG_STIMMEINGABE_PLAUSIS_ENABLED, "false"));

  /**
   * HINT: Möglicherweise müssen nicht alle Stimmeingaben plausibilisiert werden!
   */
  void fillStimmeingabePlausis(Ergebniseingang ergebniseingang);

  default void logStimmeingabePlausis(StimmeingabePlausiBuilderContext context, Collection<Stimmeingabe> stimmeingaben) {
    if (LOG_STIMMEINGABE_PLAUSIS_ENABLED) {
      Collection<Stimmeingabe> result = new HashSet<>(stimmeingaben);
      result.addAll(context.getStimmeingabenPerTk().values());

      logStimmeingabePlausis(result);
    }
  }

  default void logStimmeingabePlausis(Collection<Stimmeingabe> stimmeingaben) {
    if (LOG_STIMMEINGABE_PLAUSIS_ENABLED) {
      LOG.info("{} - Plausis", getClass().getSimpleName());

      Collection<Class< ? >> stimmeingabePlausiClasses = new HashSet<>();

      stimmeingabePlausiClasses.addAll(stimmeingaben.stream() //
          .filter(stimmeingabe -> nonNull(stimmeingabe) && nonNull(stimmeingabe.getStimmeingabePlausis())) //
          .flatMap(stimmeingabe -> stimmeingabe.getStimmeingabePlausis().stream()) //
          .filter(Objects::nonNull) //
          .map(StimmeingabePlausi::getClass) //
          .collect(toSet()));

      if (stimmeingabePlausiClasses.isEmpty()) {
        LOG.warn("\t- KEINE Plausis an Stimmeingaben gefunden");
      } else {
        stimmeingabePlausiClasses.forEach(clazz -> LOG.info("\t- {}", clazz.getSimpleName()));
      }
    }
  }
}
