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

import java.io.Serializable;
import java.util.Optional;

import de.ivu.elect.business.ergebnis.entity.Ergebnisart;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.stimmeingabe.entity.StimmeingabePlausiGebietsart;
import de.ivu.elect.business.wahl.entity.UmgangAWerte;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.business.wahl.entity.Wahlart;
import de.ivu.elect.business.wahl.entity.WahlartErgebnisart;

public class UmgangAWerteKonfiguration implements Serializable {

  private static final long serialVersionUID = 1L;

  public UmgangAWerteKonfiguration() {
    super();
  }

  public boolean isAnyAnzahlWahlberechtigteAmGebietErfassbar(Wahl wahl) {
    return isAnyAnzahlWahlberechtigteAmGebietErfassbar(wahl, Ergebnisart.VORLAEUFIG) || isAnyAnzahlWahlberechtigteAmGebietErfassbar(wahl, Ergebnisart.ENDGUELTIG);
  }

  public boolean isAnyAnzahlWahlberechtigteAmGebietErfassbar(Wahl wahl, WahlartErgebnisart ergebniseingangsart) {
    // NOTE ELECTSL-74, dass "Wahlberechtigte insgesamt" BERECHNET und NICHT am Gebiet ERFASST ODER IMPORTIERT werden!!!
    return getUmgangWahlberechtigteOhneWahlschein(wahl, ergebniseingangsart).isAWertAmGebietErfassbar() || getUmgangWahlberechtigteMitWahlschein(wahl, ergebniseingangsart).isAWertAmGebietErfassbar()
        || getUmgangWahlberechtigteNichtImWaehlerverzeichnis(wahl, ergebniseingangsart).isAWertAmGebietErfassbar();
  }

  public boolean isAnzahlWahlberechtigteOhneWahlscheinAmGebietErfassbar(Wahl wahl) {
    return getUmgangWahlberechtigteOhneWahlschein(wahl, Ergebnisart.VORLAEUFIG).isAWertAmGebietErfassbar()
        || getUmgangWahlberechtigteOhneWahlschein(wahl, Ergebnisart.ENDGUELTIG).isAWertAmGebietErfassbar();
  }

  public boolean isAnzahlWahlberechtigteMitWahlscheinAmGebietErfassbar(Wahl wahl) {
    return getUmgangWahlberechtigteMitWahlschein(wahl, Ergebnisart.VORLAEUFIG).isAWertAmGebietErfassbar()
        || getUmgangWahlberechtigteMitWahlschein(wahl, Ergebnisart.ENDGUELTIG).isAWertAmGebietErfassbar();
  }

  public boolean isAnzahlWahlberechtigteNichtImWaehlerverzeichnisAmGebietErfassbar(Wahl wahl) {
    return getUmgangWahlberechtigteNichtImWaehlerverzeichnis(wahl, Ergebnisart.VORLAEUFIG).isAWertAmGebietErfassbar()
        || getUmgangWahlberechtigteNichtImWaehlerverzeichnis(wahl, Ergebnisart.ENDGUELTIG).isAWertAmGebietErfassbar();
  }

  public boolean isPruefkennzeichenWahlberechtigteImportNotwendig(Wahl wahl) {
    return getUmgangPruefkennzeichenWahlberechtigte(wahl, Ergebnisart.VORLAEUFIG).isAWerteImportNotwendig()
        || getUmgangPruefkennzeichenWahlberechtigte(wahl, Ergebnisart.ENDGUELTIG).isAWerteImportNotwendig();
  }

  public boolean isAnyAnzahlWahlberechtigteImportNotwendig(Wahl wahl) {
    return isAnyAnzahlWahlberechtigteImportNotwendig(wahl, Ergebnisart.VORLAEUFIG) || isAnyAnzahlWahlberechtigteImportNotwendig(wahl, Ergebnisart.ENDGUELTIG);
  }

  public boolean isAnyAnzahlWahlberechtigteImportNotwendig(Wahl wahl, WahlartErgebnisart ergebniseingangsart) {
    // NOTE ELECTSL-74, dass "Wahlberechtigte insgesamt" BERECHNET und NICHT am Gebiet ERFASST ODER IMPORTIERT werden!!!
    return getUmgangWahlberechtigteOhneWahlschein(wahl, ergebniseingangsart).isAWerteImportNotwendig() || getUmgangWahlberechtigteMitWahlschein(wahl, ergebniseingangsart).isAWerteImportNotwendig()
        || getUmgangWahlberechtigteNichtImWaehlerverzeichnis(wahl, ergebniseingangsart).isAWerteImportNotwendig();
  }

  public boolean isAnzahlWahlberechtigteOhneWahlscheinImportNotwendig(Wahl wahl) {
    return getUmgangWahlberechtigteOhneWahlschein(wahl, Ergebnisart.VORLAEUFIG).isAWerteImportNotwendig()
        || getUmgangWahlberechtigteOhneWahlschein(wahl, Ergebnisart.ENDGUELTIG).isAWerteImportNotwendig();
  }

  public boolean isAnzahlWahlberechtigteMitWahlscheinImportNotwendig(Wahl wahl) {
    return getUmgangWahlberechtigteMitWahlschein(wahl, Ergebnisart.VORLAEUFIG).isAWerteImportNotwendig()
        || getUmgangWahlberechtigteMitWahlschein(wahl, Ergebnisart.ENDGUELTIG).isAWerteImportNotwendig();
  }

  public boolean isAnzahlWahlberechtigteNichtImWaehlerverzeichnisImportNotwendig(Wahl wahl) {
    return getUmgangWahlberechtigteNichtImWaehlerverzeichnis(wahl, Ergebnisart.VORLAEUFIG).isAWerteImportNotwendig()
        || getUmgangWahlberechtigteNichtImWaehlerverzeichnis(wahl, Ergebnisart.ENDGUELTIG).isAWerteImportNotwendig();
  }

  public UmgangAWerte getUmgangPruefkennzeichenWahlberechtigte(Wahl wahl, WahlartErgebnisart ergebnisart) {
    Wahlart wahlart = wahl.getWahlart();

    if (ergebnisart.isEndgueltig()) {
      return wahlart.getUmgangAPruefkennzeichenEndgueltig();
    }

    if (ergebnisart.isVorlaeufig()) {
      return wahlart.getUmgangAPruefkennzeichenVorlaeufig();
    }

    throw new IllegalArgumentException("Unbekannte Ergebnisart: " + ergebnisart);
  }

  public UmgangAWerte getUmgangWahlberechtigteOhneWahlschein(Wahl wahl, WahlartErgebnisart ergebnisart) {
    Wahlart wahlart = wahl.getWahlart();

    if (ergebnisart.isEndgueltig()) {
      return wahlart.getUmgangAOhneWahlscheinEndgueltig();
    }

    if (ergebnisart.isVorlaeufig()) {
      return wahlart.getUmgangAOhneWahlscheinVorlaeufig();
    }

    throw new IllegalArgumentException("Unbekannte Ergebnisart: " + ergebnisart);
  }

  public UmgangAWerte getUmgangWahlberechtigteMitWahlschein(Wahl wahl, WahlartErgebnisart ergebnisart) {
    Wahlart wahlart = wahl.getWahlart();

    if (ergebnisart.isEndgueltig()) {
      return wahlart.getUmgangAMitWahlscheinEndgueltig();
    }

    if (ergebnisart.isVorlaeufig()) {
      return wahlart.getUmgangAMitWahlscheinVorlaeufig();
    }

    throw new IllegalArgumentException("Unbekannte Ergebnisart: " + ergebnisart);
  }

  public UmgangAWerte getUmgangWahlberechtigteNichtImWaehlerverzeichnis(Wahl wahl, WahlartErgebnisart ergebnisart) {
    Wahlart wahlart = wahl.getWahlart();

    if (ergebnisart.isEndgueltig()) {
      return wahlart.getUmgangANichtImWaehlerverzeichnisEndgueltig();
    }

    if (ergebnisart.isVorlaeufig()) {
      return wahlart.getUmgangANichtImWaehlerverzeichnisVorlaeufig();
    }

    throw new IllegalArgumentException("Unbekannte Ergebnisart: " + ergebnisart);
  }

  public UmgangAWerte getUmgangWahlberechtigteGesamt(Wahl wahl, WahlartErgebnisart ergebnisart) {
    Wahlart wahlart = wahl.getWahlart();

    if (ergebnisart.isEndgueltig()) {
      return wahlart.getUmgangAGesamtEndgueltig();
    }

    if (ergebnisart.isVorlaeufig()) {
      return wahlart.getUmgangAGesamtVorlaeufig();
    }

    throw new IllegalArgumentException("Unbekannte Ergebnisart: " + ergebnisart);
  }

  public boolean isPruefkennzeichenWahlberechtigteBeiStimmeingabeRelevant(Wahl wahl, WahlartErgebnisart ergebnisart, Optional<StimmeingabePlausiGebietsart> gebietsart) {
    return isPruefkennzeichenWahlberechtigteBeiGebietsartRelevant(gebietsart) && getUmgangPruefkennzeichenWahlberechtigte(wahl, ergebnisart).isAWertBeiStimmeingabeZuErfassenOderAnzuzeigen();
  }

  public boolean isPruefkennzeichenWahlberechtigteBeiStimmeingabeZuPlausibilisieren(Wahl wahl, WahlartErgebnisart ergebnisart, Optional<StimmeingabePlausiGebietsart> gebietsart) {
    return isPruefkennzeichenWahlberechtigteBeiGebietsartRelevant(gebietsart) && getUmgangPruefkennzeichenWahlberechtigte(wahl, ergebnisart).isAWertBeiStimmeingabeZuErfassen();
  }

  public boolean isPruefkennzeichenWahlberechtigteBeiStimmeingabeZuPlausibilisierenGegenPruefkennzeichenWahlberechtigteAmGebiet(Wahl wahl, WahlartErgebnisart ergebnisart,
      Optional<StimmeingabePlausiGebietsart> gebietsart) {
    return isPruefkennzeichenWahlberechtigteBeiGebietsartRelevant(gebietsart)
        && getUmgangPruefkennzeichenWahlberechtigte(wahl, ergebnisart).isAWertBeiStimmeingabeZuPlausibilisierenGegenAWertAmGebiet();
  }

  public boolean isPruefkennzeichenWahlberechtigteBeiGebietsartRelevant(Gebiet wahldurchfuehrungsgebiet) {
    return isPruefkennzeichenWahlberechtigteBeiGebietsartRelevant(findStimmeingabePlausiGebietsart(wahldurchfuehrungsgebiet));
  }

  public boolean isPruefkennzeichenWahlberechtigteBeiGebietsartRelevant(Optional<StimmeingabePlausiGebietsart> gebietsart) {
    // NOTE, dass diese Methode aus Konsistenzgründen existiert! Im Gegensatz zu den anderen Wahlberechtigte-Werten, wir dass Prüfkennzeichen (bisher) bei allen Gebietsarten angezeigt.
    return true;
  }

  public boolean isWahlberechtigteOhneWahlscheinBeiStimmeingabeRelevant(Wahl wahl, WahlartErgebnisart ergebnisart, Optional<StimmeingabePlausiGebietsart> gebietsart) {
    return isWahlberechtigteOhneWahlscheinBeiGebietsartRelevant(gebietsart) && getUmgangWahlberechtigteOhneWahlschein(wahl, ergebnisart).isAWertBeiStimmeingabeZuErfassenOderAnzuzeigen();
  }

  public boolean isWahlberechtigteOhneWahlscheinBeiStimmeingabeZuPlausibilisieren(Wahl wahl, WahlartErgebnisart ergebnisart, Optional<StimmeingabePlausiGebietsart> gebietsart) {
    return isWahlberechtigteOhneWahlscheinBeiGebietsartRelevant(gebietsart) && getUmgangWahlberechtigteOhneWahlschein(wahl, ergebnisart).isAWertBeiStimmeingabeZuErfassen();
  }

  public boolean isWahlberechtigteOhneWahlscheinBeiStimmeingabeZuPlausibilisierenGegenWahlberechtigteOhneWahlscheinAmGebiet(Wahl wahl, WahlartErgebnisart ergebnisart,
      Optional<StimmeingabePlausiGebietsart> gebietsart) {
    return isWahlberechtigteOhneWahlscheinBeiGebietsartRelevant(gebietsart) && getUmgangWahlberechtigteOhneWahlschein(wahl, ergebnisart).isAWertBeiStimmeingabeZuPlausibilisierenGegenAWertAmGebiet();
  }

  public boolean isWahlberechtigteOhneWahlscheinBeiGebietsartRelevant(Gebiet wahldurchfuehrungsgebiet) {
    return isWahlberechtigteOhneWahlscheinBeiGebietsartRelevant(findStimmeingabePlausiGebietsart(wahldurchfuehrungsgebiet));
  }

  public boolean isWahlberechtigteOhneWahlscheinBeiGebietsartRelevant(Optional<StimmeingabePlausiGebietsart> gebietsart) {
    return isWahlberechtigteBeiGebietsartRelevant(gebietsart);
  }

  public boolean isWahlberechtigteMitWahlscheinBeiStimmeingabeRelevant(Wahl wahl, WahlartErgebnisart ergebnisart, Optional<StimmeingabePlausiGebietsart> gebietsart) {
    return isWahlberechtigteMitWahlscheinBeiGebietsartRelevant(gebietsart) && getUmgangWahlberechtigteMitWahlschein(wahl, ergebnisart).isAWertBeiStimmeingabeZuErfassenOderAnzuzeigen();
  }

  public boolean isWahlberechtigteMitWahlscheinBeiStimmeingabeZuPlausibilisieren(Wahl wahl, WahlartErgebnisart ergebnisart, Optional<StimmeingabePlausiGebietsart> gebietsart) {
    return isWahlberechtigteMitWahlscheinBeiGebietsartRelevant(gebietsart) && getUmgangWahlberechtigteMitWahlschein(wahl, ergebnisart).isAWertBeiStimmeingabeZuErfassen();
  }

  public boolean isWahlberechtigteMitWahlscheinBeiStimmeingabeZuPlausibilisierenGegenWahlberechtigteMitWahlscheinAmGebiet(Wahl wahl, WahlartErgebnisart ergebnisart,
      Optional<StimmeingabePlausiGebietsart> gebietsart) {
    return isWahlberechtigteMitWahlscheinBeiGebietsartRelevant(gebietsart) && getUmgangWahlberechtigteMitWahlschein(wahl, ergebnisart).isAWertBeiStimmeingabeZuPlausibilisierenGegenAWertAmGebiet();
  }

  public boolean isWahlberechtigteMitWahlscheinBeiGebietsartRelevant(Gebiet wahldurchfuehrungsgebiet) {
    return isWahlberechtigteMitWahlscheinBeiGebietsartRelevant(findStimmeingabePlausiGebietsart(wahldurchfuehrungsgebiet));
  }

  public boolean isWahlberechtigteMitWahlscheinBeiGebietsartRelevant(Optional<StimmeingabePlausiGebietsart> gebietsart) {
    return isWahlberechtigteBeiGebietsartRelevant(gebietsart);
  }

  public boolean isWahlberechtigteNichtImWaehlerverzeichnisBeiStimmeingabeRelevant(Wahl wahl, WahlartErgebnisart ergebnisart, Optional<StimmeingabePlausiGebietsart> gebietsart) {
    return isWahlberechtigteNichtImWaehlerverzeichnisBeiGebietsartRelevant(gebietsart)
        && getUmgangWahlberechtigteNichtImWaehlerverzeichnis(wahl, ergebnisart).isAWertBeiStimmeingabeZuErfassenOderAnzuzeigen();
  }

  public boolean isWahlberechtigteNichtImWaehlerverzeichnisBeiStimmeingabeZuPlausibilisieren(Wahl wahl, WahlartErgebnisart ergebnisart, Optional<StimmeingabePlausiGebietsart> gebietsart) {
    return isWahlberechtigteNichtImWaehlerverzeichnisBeiGebietsartRelevant(gebietsart) && getUmgangWahlberechtigteNichtImWaehlerverzeichnis(wahl, ergebnisart).isAWertBeiStimmeingabeZuErfassen();
  }

  public boolean isWahlberechtigteNichtImWaehlerverzeichnisBeiStimmeingabeZuPlausibilisierenGegenWahlberechtigteNichtImWaehlerverzeichnisAmGebiet(Wahl wahl, WahlartErgebnisart ergebnisart,
      Optional<StimmeingabePlausiGebietsart> gebietsart) {
    return isWahlberechtigteNichtImWaehlerverzeichnisBeiGebietsartRelevant(gebietsart)
        && getUmgangWahlberechtigteNichtImWaehlerverzeichnis(wahl, ergebnisart).isAWertBeiStimmeingabeZuPlausibilisierenGegenAWertAmGebiet();
  }

  public boolean isWahlberechtigteNichtImWaehlerverzeichnisBeiGebietsartRelevant(Gebiet wahldurchfuehrungsgebiet) {
    return isWahlberechtigteNichtImWaehlerverzeichnisBeiGebietsartRelevant(findStimmeingabePlausiGebietsart(wahldurchfuehrungsgebiet));
  }

  public boolean isWahlberechtigteNichtImWaehlerverzeichnisBeiGebietsartRelevant(Optional<StimmeingabePlausiGebietsart> gebietsart) {
    return isWahlberechtigteBeiGebietsartRelevant(gebietsart);
  }

  public boolean isWahlberechtigteGesamtBeiStimmeingabeZuPlausibilisieren(Wahl wahl, WahlartErgebnisart ergebnisart, Optional<StimmeingabePlausiGebietsart> gebietsart) {
    return isWahlberechtigteGesamtBeiGebietsartRelevant(gebietsart) && getUmgangWahlberechtigteGesamt(wahl, ergebnisart).isAWertBeiStimmeingabeZuErfassen();
  }

  public boolean isWahlberechtigteGesamtBeiStimmeingabeZuPlausibilisierenGegenWahlberechtigteGesamtAmGebiet(Wahl wahl, WahlartErgebnisart ergebnisart,
      Optional<StimmeingabePlausiGebietsart> gebietsart) {
    return isWahlberechtigteGesamtBeiGebietsartRelevant(gebietsart) && getUmgangWahlberechtigteGesamt(wahl, ergebnisart).isAWertBeiStimmeingabeZuPlausibilisierenGegenAWertAmGebiet();
  }

  public boolean isWahlberechtigteGesamtBeiStimmeingabeRelevant(Wahl wahl, WahlartErgebnisart ergebnisart, Optional<StimmeingabePlausiGebietsart> gebietsart) {
    return isWahlberechtigteGesamtBeiGebietsartRelevant(gebietsart) && getUmgangWahlberechtigteGesamt(wahl, ergebnisart).isAWertBeiStimmeingabeZuErfassenOderAnzuzeigen();
  }

  public boolean isWahlberechtigteGesamtBeiGebietsartRelevant(Gebiet wahldurchfuehrungsgebiet) {
    return isWahlberechtigteGesamtBeiGebietsartRelevant(findStimmeingabePlausiGebietsart(wahldurchfuehrungsgebiet));
  }

  public boolean isWahlberechtigteGesamtBeiGebietsartRelevant(Optional<StimmeingabePlausiGebietsart> gebietsart) {
    return isWahlberechtigteBeiGebietsartRelevant(gebietsart);
  }

  protected boolean isWahlberechtigteBeiGebietsartRelevant(Optional<StimmeingabePlausiGebietsart> gebietsart) {
    return !isBriefwahlbezirk(gebietsart);
  }

  protected boolean isBriefwahlbezirk(Optional<StimmeingabePlausiGebietsart> gebietsart) {
    return gebietsart.map(StimmeingabePlausiGebietsart::isBriefwahlbezirk).orElse(false);
  }

  protected Optional<StimmeingabePlausiGebietsart> findStimmeingabePlausiGebietsart(Gebiet wahldurchfuehrungsgebiet) {
    return Optional.empty();
  }
}
