
package de.ivu.elect.business.wahlvorschlag.entity;

import static java.util.Arrays.stream;
import static java.util.Objects.nonNull;
import static java.util.stream.Collectors.toList;

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

import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.business.wahl.entity.WahlParameter;
import de.ivu.elect.business.wahl.entity.WahlParameterLoader;
import de.ivu.elect.business.wahl.entity.WahlParameterLoaderContext;
import de.ivu.elect.business.wahl.entity.WahlParameterWahlvorschlagsdokumentWahlvorschlagArt;
import de.ivu.elect.business.wahl.entity.WahlParameterWerte;

public abstract class AbstractWahlvorschlagsdokument implements WahlvorschlagsdokumentBase {

  private static final long serialVersionUID = 1L;

  public AbstractWahlvorschlagsdokument() {
    super();
  }

  public static List<Wahlvorschlagsdokument> filterWahlvorschlagsdokumenteEditable(WahlParameterLoader wahlParameterLoader, Wahl wahl,
      Wahlvorschlag wahlvorschlag, Collection<Wahlvorschlagsdokument> wahlvorschlagsdokumente) {
    return wahlvorschlagsdokumente.stream() //
        .filter(wahlvorschlagsdokument -> isWahlParameterConfigured(wahlParameterLoader, wahl, wahlvorschlag, wahlvorschlagsdokument)
            || isAnzahlPersisted(wahlvorschlagsdokument)) //
        .collect(toList());
  }

  private static boolean isWahlParameterConfigured(WahlParameterLoader wahlParameterLoader, Wahl wahl, Wahlvorschlag wahlvorschlag,
      Wahlvorschlagsdokument wahlvorschlagsdokument) {
    WahlvorschlagsdokumentArt wahlvorschlagsdokumentArt = wahlvorschlagsdokument.getWahlvorschlagsdokumentArt();

    return findWahlParameter(wahlParameterLoader, wahl, wahlvorschlagsdokumentArt) //
        .map(wahlParameter -> {
          List<WahlParameterWahlvorschlagsdokumentWahlvorschlagArt> valuesMatching = new ArrayList<>();
          valuesMatching.add(WahlParameterWahlvorschlagsdokumentWahlvorschlagArt.ALLE);

          if (wahlvorschlag.isListe()) {
            valuesMatching.add(WahlParameterWahlvorschlagsdokumentWahlvorschlagArt.LISTE);
          }

          if (wahlvorschlag.isDirektkandidat()) {
            valuesMatching.add(WahlParameterWahlvorschlagsdokumentWahlvorschlagArt.KANDIDAT);
          }

          return valuesMatching.contains(wahlParameter.getWertEnumValue());
        }) //
        .orElse(false);
  }

  private static Optional<WahlParameter> findWahlParameter(WahlParameterLoader wahlParameterLoader, Wahl wahl,
      WahlvorschlagsdokumentArt wahlvorschlagsdokumentArt) {
    return stream(WahlParameterWerte.values()) //
        .filter(template -> template.name().equals("WAHLVORSCHLAGSDOKUMENT_" + wahlvorschlagsdokumentArt.name())) //
        .findFirst() //
        .map(template -> wahlParameterLoader.getParameter(new WahlParameterLoaderContext(wahl, template)));
  }

  private static boolean isAnzahlPersisted(Wahlvorschlagsdokument wahlvorschlagsdokument) {
    Long anzahl = wahlvorschlagsdokument.getAnzahl();

    return wahlvorschlagsdokument.isPersistent() && nonNull(anzahl) && anzahl > 0;
  }
}
