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

import static de.ivu.elect.business.stimmeingabe.entity.StimmeingabePlausiFehlerart.ERROR;
import static de.ivu.elect.business.stimmeingabe.entity.StimmeingabePlausiFehlerart.WARNING;
import static de.ivu.elect.business.stimmeingabe.entity.StimmeingabePlausiGebietsart.BRIEFWAHLBEZIRK;
import static de.ivu.elect.business.stimmeingabe.entity.StimmeingabePlausiGebietsart.BRIEFWAHLBEZIRK_SONDERSTIMMBEZIRK;
import static de.ivu.elect.business.stimmeingabe.entity.StimmeingabePlausiGebietsart.URNENWAHLBEZIRK;
import static de.ivu.elect.business.stimmeingabe.entity.StimmeingabePlausiGebietsart.URNENWAHLBEZIRK_SONDERSTIMMBEZIRK;
import static de.ivu.elect.business.stimmeingabe.entity.StimmeingabePlausiTyp.PRUEFKENNZEICHEN_WAHLBERECHTIGTE_ERFASST;
import static de.ivu.elect.business.stimmeingabe.entity.StimmeingabePlausiTyp.PRUEFKENNZEICHEN_WAHLBERECHTIGTE_GLEICH_PRUEFKENNZEICHEN_WAHLBERECHTIGTE_AM_GEBIET;
import static de.ivu.elect.business.stimmeingabe.entity.StimmeingabePlausiTyp.STIMMEINGABE_ANZAHL_IN_VORSTUFEN_GLEICH;
import static de.ivu.elect.business.stimmeingabe.entity.StimmeingabePlausiTyp.STIMMEINGABE_ANZAHL_KONVERTIERBAR;
import static de.ivu.elect.business.stimmeingabe.entity.StimmeingabePlausiTyp.STIMMZETTEL_GESAMT_ANZAHL_GLEICH_WAEHLER_GESAMT_ANZAHL;
import static de.ivu.elect.business.stimmeingabe.entity.StimmeingabePlausiTyp.STIMMZETTEL_GESAMT_ANZAHL_GLEICH_WAEHLER_GESAMT_ANZAHL_MINUS_STIMMZETTEL_ZUWENIG_ANZAHL;
import static de.ivu.elect.business.stimmeingabe.entity.StimmeingabePlausiTyp.STIMMZETTEL_GESAMT_ANZAHL_GLEICH_WAEHLER_GESAMT_ANZAHL_PLUS_STIMMZETTEL_ZUVIEL_ANZAHL;
import static de.ivu.elect.business.stimmeingabe.entity.StimmeingabePlausiTyp.STIMMZETTEL_GESAMT_ANZAHL_GROESSER_NULL;
import static de.ivu.elect.business.stimmeingabe.entity.StimmeingabePlausiTyp.STIMMZETTEL_GESAMT_ANZAHL_KLEINER_GLEICH_WAHLBERECHTIGTE_GESAMT_ANZAHL;
import static de.ivu.elect.business.stimmeingabe.entity.StimmeingabePlausiTyp.STIMMZETTEL_GESAMT_ANZAHL_UNGLEICH_WAEHLER_GESAMT_ANZAHL;
import static de.ivu.elect.business.stimmeingabe.entity.StimmeingabePlausiTyp.WAEHLER_GESAMT_ANZAHL_GLEICH_WAEHLER_ANZAHLEN_SUMME;
import static de.ivu.elect.business.stimmeingabe.entity.StimmeingabePlausiTyp.WAHLBERECHTIGTE_GESAMT_ANZAHL_GLEICH_ANZAHL_AM_GEBIET;
import static de.ivu.elect.business.stimmeingabe.entity.StimmeingabePlausiTyp.WAHLBERECHTIGTE_GESAMT_ANZAHL_GROESSER_NULL;

import java.util.Optional;

import javax.inject.Inject;

import de.ivu.elect.business.stimmeingabe.control.NlStimmeingabeKopfzahlKonfiguration;
import de.ivu.elect.business.stimmeingabe.entity.StimmeingabePlausiErgebniseingangsart;
import de.ivu.elect.business.stimmeingabe.entity.StimmeingabePlausiGebietsart;
import de.ivu.elect.business.stimmeingabe.entity.StimmeingabePlausiTyp;
import de.ivu.elect.business.wahl.boundary.WahlartTemplate;
import de.ivu.elect.business.wahl.entity.Wahl;

public abstract class AbstractNlStimmeingabePlausiDefinitions extends AbstractStimmeingabePlausiDefinitions {

  public static final StimmeingabePlausiTyp STIMMZETTEL_EINGENOMMEN_GESAMT_ANZAHL_GROESSER_NULL = STIMMZETTEL_GESAMT_ANZAHL_GROESSER_NULL;

  public static final StimmeingabePlausiTyp STIMMZETTEL_EINGENOMMEN_GESAMT_ANZAHL_KLEINER_GLEICH_WAHLBERECHTIGTE_GESAMT_ANZAHL = STIMMZETTEL_GESAMT_ANZAHL_KLEINER_GLEICH_WAHLBERECHTIGTE_GESAMT_ANZAHL;

  public static final StimmeingabePlausiTyp STIMMZETTEL_EINGENOMMEN_GESAMT_ANZAHL_GLEICH_WAEHLER_GESAMT_ANZAHL = STIMMZETTEL_GESAMT_ANZAHL_GLEICH_WAEHLER_GESAMT_ANZAHL;

  public static final StimmeingabePlausiTyp STIMMZETTEL_EINGENOMMEN_GESAMT_ANZAHL_UNGLEICH_WAEHLER_GESAMT_ANZAHL = STIMMZETTEL_GESAMT_ANZAHL_UNGLEICH_WAEHLER_GESAMT_ANZAHL;

  public static final StimmeingabePlausiTyp STIMMZETTEL_EINGENOMMEN_ABWEICHEND_ZUWENIG_ANZAHL_GLEICH_WAEHLER_GESAMT_ANZAHL_MINUS_STIMMZETTEL_EINGENOMMEN_GESAMT_ANZAHL = STIMMZETTEL_GESAMT_ANZAHL_GLEICH_WAEHLER_GESAMT_ANZAHL_MINUS_STIMMZETTEL_ZUWENIG_ANZAHL;

  public static final StimmeingabePlausiTyp STIMMZETTEL_EINGENOMMEN_ABWEICHEND_ZUVIEL_ANZAHL_GLEICH_STIMMZETTEL_EINGENOMMEN_GESAMT_ANZAHL_MINUS_WAEHLER_GESAMT_ANZAHL = STIMMZETTEL_GESAMT_ANZAHL_GLEICH_WAEHLER_GESAMT_ANZAHL_PLUS_STIMMZETTEL_ZUVIEL_ANZAHL;

  @Inject
  private transient NlStimmeingabeKopfzahlKonfiguration nlStimmeingabeKopfzahlKonfiguration;

  public AbstractNlStimmeingabePlausiDefinitions(WahlartTemplate wahlartTemplate) {
    super(wahlartTemplate);
  }

  protected NlStimmeingabeKopfzahlKonfiguration getStimmeingabeKopfzahlKonfiguration() {
    return nlStimmeingabeKopfzahlKonfiguration;
  }

  /*
   * ELECT-9588, ggf. auch NlDefaultListenwahlStimmeingabePlausiBuilder um Listenstimmen-Plausis ergänzen!
   */

  @Override
  protected void initDefaultsAlleGebietsarten(StimmeingabePlausiDefinitionsContext context, Wahl wahl, StimmeingabePlausiErgebniseingangsart ergebniseingangsart) {
    for (StimmeingabePlausiGebietsart gebietsart : StimmeingabePlausiGebietsart.values()) {
      initDefault(ergebniseingangsart, gebietsart, STIMMEINGABE_ANZAHL_KONVERTIERBAR, ERROR); // ELECTVAPP-37, #1

      initDefault(ergebniseingangsart, gebietsart, PRUEFKENNZEICHEN_WAHLBERECHTIGTE_ERFASST, ERROR);
      initDefault(ergebniseingangsart, gebietsart, PRUEFKENNZEICHEN_WAHLBERECHTIGTE_GLEICH_PRUEFKENNZEICHEN_WAHLBERECHTIGTE_AM_GEBIET, ERROR);

      // NOTE ELECT-9851, Wahlberechtigte eigentlich nur relevant für Urnenwahlbezirke, aber laut Ticket werden AUCH IN BRIEFWAHLBEZIRKEN WAHLBERECHTIGTE angezeigt/erfasst...
      initDefault(ergebniseingangsart, gebietsart, WAHLBERECHTIGTE_GESAMT_ANZAHL_GLEICH_ANZAHL_AM_GEBIET, ERROR);
      initDefault(ergebniseingangsart, gebietsart, WAHLBERECHTIGTE_GESAMT_ANZAHL_GROESSER_NULL, WARNING); // ELECTVAPP-37, #13

      boolean waehlerGesamtBeiStimmeingabeRelevant = isWaehlerGesamtBeiStimmeingabeRelevant(wahl, ergebniseingangsart, gebietsart);

      if (waehlerGesamtBeiStimmeingabeRelevant) {
        initDefault(ergebniseingangsart, gebietsart, WAEHLER_GESAMT_ANZAHL_GLEICH_WAEHLER_ANZAHLEN_SUMME, WARNING); // ELECTVAPP-37, #2
      }

      if (isWahlberechtigteGesamtBeiStimmeingabeRelevant(wahl, ergebniseingangsart, gebietsart)) { // ELECTVAPP-980, ELECTVAPP-981
        // NOTE ELECT-9851, Wahlberechtigte eigentlich nur relevant für Urnenwahlbezirke, aber laut Ticket werden AUCH IN BRIEFWAHLBEZIRKEN WAHLBERECHTIGTE angezeigt/erfasst...
        initDefault(ergebniseingangsart, gebietsart, STIMMZETTEL_EINGENOMMEN_GESAMT_ANZAHL_KLEINER_GLEICH_WAHLBERECHTIGTE_GESAMT_ANZAHL, WARNING); // ELECTVAPP-37, #9
      }

      if (isStimmzettelEingenommenGesamtBeiStimmeingabeRelevant(wahl, ergebniseingangsart, gebietsart)) {
        initDefault(ergebniseingangsart, gebietsart, STIMMZETTEL_EINGENOMMEN_GESAMT_ANZAHL_GROESSER_NULL, WARNING); // ELECTVAPP-37, #7

        if (waehlerGesamtBeiStimmeingabeRelevant) {
          initDefault(ergebniseingangsart, gebietsart, STIMMZETTEL_EINGENOMMEN_GESAMT_ANZAHL_GLEICH_WAEHLER_GESAMT_ANZAHL, WARNING); // ELECTVAPP-37, #8
          initDefault(ergebniseingangsart, gebietsart, STIMMZETTEL_EINGENOMMEN_GESAMT_ANZAHL_UNGLEICH_WAEHLER_GESAMT_ANZAHL, WARNING);

          initDefault(ergebniseingangsart, gebietsart, STIMMZETTEL_EINGENOMMEN_ABWEICHEND_ZUVIEL_ANZAHL_GLEICH_STIMMZETTEL_EINGENOMMEN_GESAMT_ANZAHL_MINUS_WAEHLER_GESAMT_ANZAHL, WARNING); // ELECTVAPP-37, #10
          initDefault(ergebniseingangsart, gebietsart, STIMMZETTEL_EINGENOMMEN_ABWEICHEND_ZUWENIG_ANZAHL_GLEICH_WAEHLER_GESAMT_ANZAHL_MINUS_STIMMZETTEL_EINGENOMMEN_GESAMT_ANZAHL, WARNING); // ELECTVAPP-37, #11
        }
      }

      initDefault(ergebniseingangsart, gebietsart, STIMMEINGABE_ANZAHL_IN_VORSTUFEN_GLEICH, WARNING); // ELECT-9839, ELECTVAPP-37, #14
    }
  }

  @Override
  protected void initDefaultsUrnenwahlbezirk(StimmeingabePlausiDefinitionsContext context, Wahl wahl, StimmeingabePlausiErgebniseingangsart ergebniseingangsart) {
    initDefaultsUrnenwahlbezirk(context, wahl, ergebniseingangsart, URNENWAHLBEZIRK);
  }

  @Override
  protected void initDefaultsUrnenwahlbezirkSonderstimmbezirk(StimmeingabePlausiDefinitionsContext context, Wahl wahl, StimmeingabePlausiErgebniseingangsart ergebniseingangsart) {
    initDefaultsUrnenwahlbezirk(context, wahl, ergebniseingangsart, URNENWAHLBEZIRK_SONDERSTIMMBEZIRK);
  }

  protected void initDefaultsUrnenwahlbezirk(StimmeingabePlausiDefinitionsContext context, Wahl wahl, StimmeingabePlausiErgebniseingangsart ergebniseingangsart,
      StimmeingabePlausiGebietsart gebietsart) {
    // To be overridden...
  }

  @Override
  protected void initDefaultsBriefwahlbezirk(StimmeingabePlausiDefinitionsContext context, Wahl wahl, StimmeingabePlausiErgebniseingangsart ergebniseingangsart) {
    initDefaultsBriefwahlbezirk(context, wahl, ergebniseingangsart, BRIEFWAHLBEZIRK);
  }

  @Override
  protected void initDefaultsBriefwahlbezirkSonderstimmbezirk(StimmeingabePlausiDefinitionsContext context, Wahl wahl, StimmeingabePlausiErgebniseingangsart ergebniseingangsart) {
    initDefaultsBriefwahlbezirk(context, wahl, ergebniseingangsart, BRIEFWAHLBEZIRK_SONDERSTIMMBEZIRK);
  }

  protected void initDefaultsBriefwahlbezirk(StimmeingabePlausiDefinitionsContext context, Wahl wahl, StimmeingabePlausiErgebniseingangsart ergebniseingangsart,
      StimmeingabePlausiGebietsart gebietsart) {
    // To be overridden...
  }

  protected boolean isWahlberechtigteGesamtBeiStimmeingabeRelevant(Wahl wahl, StimmeingabePlausiErgebniseingangsart ergebniseingangsart, StimmeingabePlausiGebietsart gebietsart) {
    return getStimmeingabeKopfzahlKonfiguration().getUmgangAWerteKonfiguration().isWahlberechtigteGesamtBeiStimmeingabeRelevant(wahl, ergebniseingangsart, Optional.of(gebietsart));
  }

  protected boolean isWaehlerGesamtBeiStimmeingabeRelevant(Wahl wahl, StimmeingabePlausiErgebniseingangsart ergebniseingangsart, StimmeingabePlausiGebietsart gebietsart) {
    return getStimmeingabeKopfzahlKonfiguration().getUmgangBWerteKonfiguration().isWaehlerGesamtBeiStimmeingabeRelevant(wahl, ergebniseingangsart, Optional.of(gebietsart));
  }

  protected boolean isStimmzettelEingenommenGesamtBeiStimmeingabeRelevant(Wahl wahl, StimmeingabePlausiErgebniseingangsart ergebniseingangsart, StimmeingabePlausiGebietsart gebietsart) {
    return getStimmeingabeKopfzahlKonfiguration().isStimmzettelEingenommenGesamtBeiStimmeingabeRelevant(wahl, ergebniseingangsart, Optional.of(gebietsart));
  }
}
