
package de.ivu.elect.business.kandidatur.boundary;

import static de.ivu.elect.jee.entity.EntityUtil.castTo;

import java.util.Collection;
import java.util.function.Function;

import javax.enterprise.inject.Specializes;
import javax.inject.Inject;

import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.gebietsbaum.entity.Wahldurchfuehrungsgebiet;
import de.ivu.elect.business.kandidatur.entity.Direktkandidatur;
import de.ivu.elect.business.kandidatur.entity.Listenkandidatur;
import de.ivu.elect.business.sitzberechnung.control.Sitzberechnungsalgorithmus;
import de.ivu.elect.business.sitzberechnung.control.SitzberechnungsalgorithmusFinder;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.business.wahl.entity.Wahldurchfuehrung;
import de.ivu.elect.business.wahlvorschlag.entity.Direktkandidat;
import de.ivu.elect.business.wahlvorschlag.entity.Liste;
import de.ivu.elect.business.wahlvorschlag.entity.Wahlvorschlag;
import de.ivu.elect.jee.faces.Messages;

@Specializes
public class WasWaehlerBenannteKandidaturKonfiguration extends WaehlerBenannteKandidaturKonfiguration {

  @Inject
  private transient SitzberechnungsalgorithmusFinder sitzberechnungsalgorithmusFinder;

  public WasWaehlerBenannteKandidaturKonfiguration() {
    super();
  }

  public boolean isWaehlerBenannteDirektkandidaturManuellAnlegenZulaessig(Gebiet gebiet, Function<Gebiet, Collection<Direktkandidat>> wahlvorschlaegeInDirektwahlgebietFct) {
    if (gebiet != null && gebiet.isInstanceOf(Wahldurchfuehrungsgebiet.class)) {
      Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet = castTo(gebiet, Wahldurchfuehrungsgebiet.class);

      if (wahldurchfuehrungsgebiet.isDirektwahlgebiet()) {
        return isWaehlerBenannteDirektkandidaturManuellErfassbar(wahldurchfuehrungsgebiet, wahlvorschlaegeInDirektwahlgebietFct.apply(wahldurchfuehrungsgebiet));
      }
    }

    return false;
  }

  protected boolean isWaehlerBenannteDirektkandidaturManuellErfassbar(Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet, Collection< ? extends Wahlvorschlag> wahlvorschlaege) {
    return false; // ELECT-9317, LEGACY!
  }

  @Override
  public String formatWaehlerBenannteDirektkandidaturSonstigeBeschreibung(Messages messages, Direktkandidatur direktkandidatur) {
    if (isWaehlerBenannteDirektkandidaturSonstige(messages, direktkandidatur)
        && !getSitzberechnungsalgorithmus(direktkandidatur.getWahl()).isBerechnetErgebnisFallsWaehlerBenannteWahlvorschlaegeSonstigeErfasst()) {
      return messages.getMessageForMessageKey(WaehlerBenannteKandidaturKonfiguration.MSG_KEY_WAEHLER_BENANNTE_DIREKTKANDIDATUR_SONSTIGE_TOOLTIP_SITZBERECHNUNG);
    }

    return super.formatWaehlerBenannteDirektkandidaturSonstigeBeschreibung(messages, direktkandidatur);
  }

  public boolean isWaehlerBenannteListeManuellAnlegenZulaessig(Gebiet gebiet, Function<Gebiet, Collection<Liste>> wahlvorschlaegeInListenwahlgebietFct) {
    if (gebiet != null && gebiet.isInstanceOf(Wahldurchfuehrungsgebiet.class)) {
      Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet = castTo(gebiet, Wahldurchfuehrungsgebiet.class);

      if (wahldurchfuehrungsgebiet.isListenwahlgebiet()) {
        Collection<Liste> wahlvorschlaege = wahlvorschlaegeInListenwahlgebietFct.apply(wahldurchfuehrungsgebiet);

        return !containsWaehlerBenannteListe(wahlvorschlaege) && isWaehlerBenannteListeManuellErfassbar(wahldurchfuehrungsgebiet, wahlvorschlaege);
      }
    }

    return false;
  }

  protected boolean isWaehlerBenannteListeManuellErfassbar(Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet, Collection< ? extends Wahlvorschlag> wahlvorschlaege) {
    return false; // LEGACY, bisher kam die Liste auf ungeklärte Weise automatisch (nur Import?) ins System!
  }

  @Override
  public String formatWaehlerBenannteListenkandidaturSonstigeBeschreibung(Messages messages, Listenkandidatur listenkandidatur) {
    if (isWaehlerBenannteListenkandidaturSonstige(messages, listenkandidatur)
        && !getSitzberechnungsalgorithmus(listenkandidatur.getWahl()).isBerechnetErgebnisFallsWaehlerBenannteWahlvorschlaegeSonstigeErfasst()) {
      return messages.getMessageForMessageKey(WaehlerBenannteKandidaturKonfiguration.MSG_KEY_WAEHLER_BENANNTE_LISTENKANDIDATUR_SONSTIGE_TOOLTIP_SITZBERECHNUNG);
    }

    return super.formatWaehlerBenannteListenkandidaturSonstigeBeschreibung(messages, listenkandidatur);
  }

  /**
   * TODO Bisher NUR in DdKommunalwahlStimmeingabePlausiBuilder verwendet -> nach AbstractPlausiBuilder verschieben?
   *
   * @deprecated Funktioniert nur für Erfassungsgebiete!!!!
   */
  @Deprecated
  public boolean existsWaehlerBenannteListe(Wahldurchfuehrungsgebiet erfassungsgebiet, Function<Gebiet, Collection<Liste>> wahlvorschlaegeInListenwahlgebietFct) {
    Wahldurchfuehrungsgebiet listenwahlgebiet = getSitzberechnungsalgorithmus(erfassungsgebiet.getWahldurchfuehrung()).getWaehlerBenannteListeListengebietFuerErfassungsgebiet(erfassungsgebiet,
        wahlvorschlaegeInListenwahlgebietFct);

    if (listenwahlgebiet != null) {
      return containsWaehlerBenannteListe(wahlvorschlaegeInListenwahlgebietFct.apply(listenwahlgebiet));
    }

    return false;
  }

  private boolean containsWaehlerBenannteListe(Collection<Liste> listen) {
    return listen.stream().anyMatch(this::isWaehlerBenannteListe);
  }

  protected Sitzberechnungsalgorithmus getSitzberechnungsalgorithmus(Wahl wahl) {
    return sitzberechnungsalgorithmusFinder.getSitzberechnungsalgorithmus(castTo(wahl, Wahldurchfuehrung.class));
  }
}
