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

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

import de.ivu.elect.business.stimmeingabe.control.plausi.NlDefaultListenwahlStimmeingabePlausiBuilder;
import de.ivu.elect.business.stimmeingabe.control.plausi.StimmeingabePlausiFormatter;
import de.ivu.elect.business.stimmeingabe.control.plausi.StimmeingabePlausiResult;
import de.ivu.elect.business.stimmeingabe.entity.Ergebniseingang;
import de.ivu.elect.business.stimmeingabe.entity.Stimmeingabe;
import de.ivu.elect.business.stimmeingabe.entity.StimmeingabePlausiErgebniseingangsart;
import de.ivu.elect.business.stimmeingabe.entity.StimmeingabePlausiFehlerart;
import de.ivu.elect.business.stimmeingabe.entity.StimmeingabePlausiStatus;
import de.ivu.elect.business.stimmeingabe.entity.StimmeingabePlausiTyp;
import de.ivu.elect.business.stimmeingabe.entity.Stimmeingabefehler;
import de.ivu.elect.business.stimmeingabe.entity.Stimmeingabefehlerart;
import de.ivu.elect.business.stimmen.boundary.NlStimmeLabelMessages;
import de.ivu.elect.business.wahl.entity.NlWahlart;
import de.ivu.elect.business.wahl.entity.Wahldurchfuehrung;

@Specializes
public class NlStimmeingabefehlerFactory extends StimmeingabefehlerFactory {

  public static final StimmeingabePlausiTyp ENDSTUFE_SPEZIFISCH_STIMMEINGABE_ANZAHL_IN_VORSTUFEN_GLEICH_STIMMEINGABE_PLAUSI_TYP = StimmeingabePlausiTyp.STIMMEINGABE_ANZAHL_IN_VORSTUFEN_GLEICH;

  public static final StimmeingabePlausiFehlerart ENDSTUFE_SPEZIFISCH_STIMMEINGABE_ANZAHL_IN_VORSTUFEN_GLEICH_STIMMEINGABE_PLAUSI_FEHLERART = StimmeingabePlausiFehlerart.ERROR;

  public static final StimmeingabePlausiTyp ENDSTUFE_SPEZIFISCH_STIMMEINGABE_NACH_BULK_IMPORT_PRUEFEN_STIMMEINGABE_PLAUSI_TYP = StimmeingabePlausiTyp.STIMMEINGABE_ANZAHL_ENDGUELTIG_GLEICH_STIMMEINGABE_ANZAHL_VORLAEUFIG;

  public static final StimmeingabePlausiFehlerart ENDSTUFE_SPEZIFISCH_STIMMEINGABE_NACH_BULK_IMPORT_PRUEFEN_STIMMEINGABE_PLAUSI_FEHLERART = StimmeingabePlausiFehlerart.WARNING;

  @Inject
  protected transient NlStimmeLabelMessages nlStimmeLabelMessages;

  @Inject
  protected transient NlDefaultListenwahlStimmeingabePlausiBuilder nlDefaultListenwahlStimmeingabePlausiBuilder;

  public NlStimmeingabefehlerFactory() {
    super();
  }

  public boolean containsAnyStimmeingabefehlerEndstufeSpezifisch(Ergebniseingang ergebniseingang) {
    for (Stimmeingabefehler stimmeingabefehler : ergebniseingang.getStimmeingabefehler()) {
      if (matchesStimmeingabefehler(stimmeingabefehler, ENDSTUFE_SPEZIFISCH_STIMMEINGABE_ANZAHL_IN_VORSTUFEN_GLEICH_STIMMEINGABE_PLAUSI_TYP,
          ENDSTUFE_SPEZIFISCH_STIMMEINGABE_ANZAHL_IN_VORSTUFEN_GLEICH_STIMMEINGABE_PLAUSI_FEHLERART)) {
        return true;
      }

      if (matchesStimmeingabefehler(stimmeingabefehler, ENDSTUFE_SPEZIFISCH_STIMMEINGABE_NACH_BULK_IMPORT_PRUEFEN_STIMMEINGABE_PLAUSI_TYP,
          ENDSTUFE_SPEZIFISCH_STIMMEINGABE_NACH_BULK_IMPORT_PRUEFEN_STIMMEINGABE_PLAUSI_FEHLERART)) {
        return true;
      }
    }

    Wahldurchfuehrung wahldurchfuehrung = ergebniseingang.getWahldurchfuehrung();

    if (wahldurchfuehrung.isWahlMitListengebieten()) {
      return nlDefaultListenwahlStimmeingabePlausiBuilder.containsAnyStimmeingabefehlerEndstufeSpezifisch(ergebniseingang);
    }

    return false;
  }

  private boolean matchesStimmeingabefehler(Stimmeingabefehler stimmeingabefehler, StimmeingabePlausiTyp stimmeingabePlausiTyp, StimmeingabePlausiFehlerart stimmeingabePlausiFehlerart) {
    return stimmeingabePlausiTyp.equals(stimmeingabefehler.getStimmeingabePlausiTyp()) && Stimmeingabefehlerart.of(stimmeingabePlausiFehlerart).equals(stimmeingabefehler.getFehlerart());
  }

  // ELECT-10371
  public Stimmeingabefehler createStimmeingabefehlerEndstufeSpezifischStimmeingabeNachBulkImportPruefen(Ergebniseingang ergebniseingangEndstufe) {
    return createStimmeingabefehlerEndstufeSpezifischStimmeingabeNachBulkImportPruefen(
        nlDefaultListenwahlStimmeingabePlausiBuilder.findKopfzahlPlausiUnspezifischStimmeingabe(ergebniseingangEndstufe));
  }

  private Stimmeingabefehler createStimmeingabefehlerEndstufeSpezifischStimmeingabeNachBulkImportPruefen(Stimmeingabe stimmeingabeEndstufe) {
    return createStimmeingabefehlerEndstufeSpezifisch(stimmeingabeEndstufe, ENDSTUFE_SPEZIFISCH_STIMMEINGABE_NACH_BULK_IMPORT_PRUEFEN_STIMMEINGABE_PLAUSI_TYP,
        ENDSTUFE_SPEZIFISCH_STIMMEINGABE_NACH_BULK_IMPORT_PRUEFEN_STIMMEINGABE_PLAUSI_FEHLERART, "", null);
  }

  // ELECT-9839, ELECTVAPP-37, #14 (Muss-Fehler beim Wahlleiter), cf. NlDefaultListenwahlStimmeingabePlausiBuilder für Kann-Fehler beim Zweiterfasser!
  public Stimmeingabefehler createStimmeingabefehlerEndstufeSpezifischStimmeingabeAnzahlInVorstufenGleich(Stimmeingabe stimmeingabeEndstufe, Stimmeingabe stimmeingabeVorstufe) {
    return createStimmeingabefehlerEndstufeSpezifisch(stimmeingabeEndstufe, ENDSTUFE_SPEZIFISCH_STIMMEINGABE_ANZAHL_IN_VORSTUFEN_GLEICH_STIMMEINGABE_PLAUSI_TYP,
        ENDSTUFE_SPEZIFISCH_STIMMEINGABE_ANZAHL_IN_VORSTUFEN_GLEICH_STIMMEINGABE_PLAUSI_FEHLERART, stimmeingabeVorstufe.getAnzahlEingabe(), stimmeingabeVorstufe.getAnzahl());
  }

  private Stimmeingabefehler createStimmeingabefehlerEndstufeSpezifisch(Stimmeingabe stimmeingabeEndstufe, StimmeingabePlausiTyp stimmeingabePlausiTyp,
      StimmeingabePlausiFehlerart stimmeingabePlausiFehlerart, String anzahlSollEingabe, Long anzahlSoll) {
    StimmeingabePlausiStatus stimmeingabePlausiStatus = StimmeingabePlausiStatus.AKTIVIERT;
    StimmeingabePlausiErgebniseingangsart stimmeingabePlausiErgebniseingangsart = StimmeingabePlausiErgebniseingangsart.of(stimmeingabeEndstufe.getErgebniseingangsart());

    String anzahlEingabe = stimmeingabeEndstufe.getAnzahlEingabe();
    Long anzahl = stimmeingabeEndstufe.getAnzahl();

    Long anzahlSollDifferenz = anzahlSoll == null ? null : anzahlSoll - anzahl;
    Long anzahlSollAnteil = null;
    String anzahlSollAnteilFormatted = "";
    boolean anzahlSollAutomatischUebernehmbar = false;

    String stimmeingabefehlerBeschreibung = new StimmeingabePlausiFormatter(nlStimmeLabelMessages).formatFehlermeldung(stimmeingabeEndstufe.getWahl(), stimmeingabePlausiErgebniseingangsart,
        stimmeingabePlausiTyp, stimmeingabePlausiFehlerart, anzahlEingabe, anzahlSoll, anzahlSollDifferenz, anzahlSollAnteil, anzahlSollAnteilFormatted);

    return fromStimmeingabePlausiResult(new StimmeingabePlausiResult(stimmeingabeEndstufe, stimmeingabePlausiTyp, stimmeingabePlausiFehlerart, stimmeingabePlausiStatus, "",
        stimmeingabefehlerBeschreibung, anzahlSollEingabe, anzahlSoll, anzahlSollAutomatischUebernehmbar, StimmeingabePlausiResult.KEIN_FIKTIVE_WERTE_FEHLER_BEHEBER));
  }

  @Override
  protected String extractFehlerbeschreibung(StimmeingabePlausiResult plausiResult) {
    String result = super.extractFehlerbeschreibung(plausiResult);

    Stimmeingabe stimmeingabe = plausiResult.getStimmeingabe();

    if (stimmeingabe != null && (NlWahlart.isNBSB(stimmeingabe.getWahl()) || NlWahlart.isNBSBC(stimmeingabe.getWahl()))) {
      result = nlStimmeLabelMessages.replaceKennungenNbsb(result);
    }

    return result;
  }
}
