
package de.ivu.elect.presentation.ergebnis.exchange;

import java.util.function.Predicate;

import javax.inject.Inject;

import org.apache.commons.lang3.StringUtils;

import de.ivu.elect.business.dokumente.entity.DokumentVorlage;
import de.ivu.elect.business.dokumente.entity.DokumentVorlageArt;
import de.ivu.elect.business.ergebnis.boundary.DefaultErgebnisdokumentTyp;
import de.ivu.elect.business.gebietsbaum.entity.Verwaltungsart;
import de.ivu.elect.jee.faces.Messages;
import de.ivu.elect.presentation.dokumente.exchange.DokumentBulkExportSearchEntryTemplate;

public class ErgebnisdokumentBulkExportDokumentVorlageFilter {

  public static final String DOKUMENT_VORLAGE_NAME_INFIX_SEITENART_ERSTE_SEITE = "Erste Seite";

  public static final String DOKUMENT_VORLAGE_NAME_INFIX_SEITENART_WEITERE_SEITEN = "Weitere Seiten";

  public static final String DOKUMENT_VORLAGE_NAME_INFIX_STIMMENART_STIMMZETTEL = "Stimmzettel";

  public static final String DOKUMENT_VORLAGE_NAME_INFIX_STIMMENART_STIMMEN = "Stimmen";

  public static final String DOKUMENT_VORLAGE_NAME_INFIX_STIMMENART_DIREKTSTIMMEN = "Direktstimmen";

  public static final String DOKUMENT_VORLAGE_NAME_INFIX_STIMMENART_LISTENSTIMMEN = "Listenstimmen";

  @Inject
  private transient Messages messages;

  public ErgebnisdokumentBulkExportDokumentVorlageFilter() {
    super();
  }

  public ErgebnisdokumentBulkExportDokumentVorlageFilter(Messages messages) {
    super();

    this.messages = messages;
  }

  public Predicate<DokumentVorlage> matchesDokumentVorlageErgebnisErsteSchnellmeldungErfassungsgebiet(DokumentVorlageArt dokumentVorlageArt) {
    return dokumentVorlage -> hasTemplateErgebnisErsteSchnellmeldung(dokumentVorlageArt, dokumentVorlage) && !hasInfixSeitenartOrStimmenartOrGebietsart(dokumentVorlage);
  }

  public Predicate<DokumentVorlage> matchesDokumentVorlageErgebnisErsteSchnellmeldungAndGebietsart(DokumentVorlageArt dokumentVorlageArt, Verwaltungsart gebietsart) {
    return dokumentVorlage -> hasTemplateErgebnisErsteSchnellmeldung(dokumentVorlageArt, dokumentVorlage) && hasInfixGebietsart(dokumentVorlage, gebietsart)
        && !hasInfixSeitenartOrStimmenart(dokumentVorlage);
  }

  protected boolean hasTemplateErgebnisErsteSchnellmeldung(DokumentVorlageArt dokumentVorlageArt, DokumentVorlage dokumentVorlage) {
    return hasDateiImportAndTemplate(DefaultErgebnisdokumentTyp.ERGEBNIS_ERSTE_SCHNELLMELDUNG, dokumentVorlageArt, dokumentVorlage);
  }

  public Predicate<DokumentVorlage> matchesDokumentVorlageErgebnisWahlniederschriftErfassungsgebiet(DokumentVorlageArt dokumentVorlageArt) {
    return dokumentVorlage -> hasTemplateErgebnisWahlniederschrift(dokumentVorlageArt, dokumentVorlage) && !hasInfixSeitenartOrStimmenartOrGebietsart(dokumentVorlage);
  }

  public Predicate<DokumentVorlage> matchesDokumentVorlageErgebnisWahlniederschriftAndGebietsart(DokumentVorlageArt dokumentVorlageArt, Verwaltungsart gebietsart) {
    return dokumentVorlage -> hasTemplateErgebnisWahlniederschrift(dokumentVorlageArt, dokumentVorlage) && hasInfixGebietsart(dokumentVorlage, gebietsart)
        && !hasInfixSeitenartOrStimmenart(dokumentVorlage);
  }

  protected boolean hasTemplateErgebnisWahlniederschrift(DokumentVorlageArt dokumentVorlageArt, DokumentVorlage dokumentVorlage) {
    return hasDateiImportAndTemplate(DefaultErgebnisdokumentTyp.ERGEBNIS_WAHLNIEDERSCHRIFT, dokumentVorlageArt, dokumentVorlage);
  }

  public Predicate<DokumentVorlage> matchesDokumentVorlageErgebnisKandidaturen(DokumentVorlageArt dokumentVorlageArt) {
    return dokumentVorlage -> hasTemplateErgebnisKandidaturen(dokumentVorlageArt, dokumentVorlage) && !hasInfixSeitenartOrStimmenart(dokumentVorlage);
  }

  public Predicate<DokumentVorlage> matchesDokumentVorlageErgebnisKandidaturenErsteSeite(DokumentVorlageArt dokumentVorlageArt) {
    return dokumentVorlage -> hasTemplateErgebnisKandidaturen(dokumentVorlageArt, dokumentVorlage) && hasInfixErsteSeite(dokumentVorlage) && !hasAnyInfixStimmenart(dokumentVorlage);
  }

  public Predicate<DokumentVorlage> matchesDokumentVorlageErgebnisKandidaturenWeitereSeiten(DokumentVorlageArt dokumentVorlageArt) {
    return dokumentVorlage -> hasTemplateErgebnisKandidaturen(dokumentVorlageArt, dokumentVorlage) && hasInfixWeitereSeiten(dokumentVorlage) && !hasAnyInfixStimmenart(dokumentVorlage);
  }

  protected boolean hasTemplateErgebnisKandidaturen(DokumentVorlageArt dokumentVorlageArt, DokumentVorlage dokumentVorlage) {
    return hasDateiImportAndTemplate(DefaultErgebnisdokumentTyp.ERGEBNIS_KANDIDATUREN, dokumentVorlageArt, dokumentVorlage);
  }

  public Predicate<DokumentVorlage> matchesDokumentVorlageErgebnisGesamtergebnis(DokumentVorlageArt dokumentVorlageArt) {
    return dokumentVorlage -> hasTemplateErgebnisGesamtergebnis(dokumentVorlageArt, dokumentVorlage) && !hasInfixSeitenartOrStimmenart(dokumentVorlage);
  }

  public Predicate<DokumentVorlage> matchesDokumentVorlageErgebnisGesamtergebnisStimmzettel(DokumentVorlageArt dokumentVorlageArt) {
    return dokumentVorlage -> hasTemplateErgebnisGesamtergebnis(dokumentVorlageArt, dokumentVorlage) && !hasAnyInfixSeite(dokumentVorlage) && hasInfixStimmzettel(dokumentVorlage);
  }

  public Predicate<DokumentVorlage> matchesDokumentVorlageErgebnisGesamtergebnisStimmen(DokumentVorlageArt dokumentVorlageArt) {
    return dokumentVorlage -> hasTemplateErgebnisGesamtergebnis(dokumentVorlageArt, dokumentVorlage) && !hasAnyInfixSeite(dokumentVorlage) && hasInfixStimmen(dokumentVorlage);
  }

  public Predicate<DokumentVorlage> matchesDokumentVorlageErgebnisGesamtergebnisErsteSeite(DokumentVorlageArt dokumentVorlageArt) {
    return dokumentVorlage -> hasTemplateErgebnisGesamtergebnis(dokumentVorlageArt, dokumentVorlage) && hasInfixErsteSeite(dokumentVorlage) && !hasAnyInfixStimmenart(dokumentVorlage);
  }

  public Predicate<DokumentVorlage> matchesDokumentVorlageErgebnisGesamtergebnisErsteSeiteDirektstimmen(DokumentVorlageArt dokumentVorlageArt) {
    return dokumentVorlage -> hasTemplateErgebnisGesamtergebnis(dokumentVorlageArt, dokumentVorlage) && hasInfixErsteSeite(dokumentVorlage) && hasInfixDirektstimmen(dokumentVorlage);
  }

  public Predicate<DokumentVorlage> matchesDokumentVorlageErgebnisGesamtergebnisErsteSeiteListenstimmen(DokumentVorlageArt dokumentVorlageArt) {
    return dokumentVorlage -> hasTemplateErgebnisGesamtergebnis(dokumentVorlageArt, dokumentVorlage) && hasInfixErsteSeite(dokumentVorlage) && hasInfixListenstimmen(dokumentVorlage);
  }

  public Predicate<DokumentVorlage> matchesDokumentVorlageErgebnisGesamtergebnisErsteSeiteStimmen(DokumentVorlageArt dokumentVorlageArt) {
    return dokumentVorlage -> hasTemplateErgebnisGesamtergebnis(dokumentVorlageArt, dokumentVorlage) && hasInfixErsteSeite(dokumentVorlage) && hasInfixStimmen(dokumentVorlage);
  }

  public Predicate<DokumentVorlage> matchesDokumentVorlageErgebnisGesamtergebnisWeitereSeiten(DokumentVorlageArt dokumentVorlageArt) {
    return dokumentVorlage -> hasTemplateErgebnisGesamtergebnis(dokumentVorlageArt, dokumentVorlage) && hasInfixWeitereSeiten(dokumentVorlage) && !hasAnyInfixStimmenart(dokumentVorlage);
  }

  public Predicate<DokumentVorlage> matchesDokumentVorlageErgebnisGesamtergebnisWeitereSeitenDirektstimmen(DokumentVorlageArt dokumentVorlageArt) {
    return dokumentVorlage -> hasTemplateErgebnisGesamtergebnis(dokumentVorlageArt, dokumentVorlage) && hasInfixWeitereSeiten(dokumentVorlage) && hasInfixDirektstimmen(dokumentVorlage);
  }

  public Predicate<DokumentVorlage> matchesDokumentVorlageErgebnisGesamtergebnisWeitereSeitenListenstimmen(DokumentVorlageArt dokumentVorlageArt) {
    return dokumentVorlage -> hasTemplateErgebnisGesamtergebnis(dokumentVorlageArt, dokumentVorlage) && hasInfixWeitereSeiten(dokumentVorlage) && hasInfixListenstimmen(dokumentVorlage);
  }

  public Predicate<DokumentVorlage> matchesDokumentVorlageErgebnisGesamtergebnisWeitereSeitenStimmen(DokumentVorlageArt dokumentVorlageArt) {
    return dokumentVorlage -> hasTemplateErgebnisGesamtergebnis(dokumentVorlageArt, dokumentVorlage) && hasInfixWeitereSeiten(dokumentVorlage) && hasInfixStimmen(dokumentVorlage);
  }

  protected boolean hasTemplateErgebnisGesamtergebnis(DokumentVorlageArt dokumentVorlageArt, DokumentVorlage dokumentVorlage) {
    return hasDateiImportAndTemplate(DefaultErgebnisdokumentTyp.ERGEBNIS_GESAMTERGEBNIS, dokumentVorlageArt, dokumentVorlage);
  }

  public Predicate<DokumentVorlage> matchesDokumentVorlageBekanntmachungWahlergebnis(DokumentVorlageArt dokumentVorlageArt) {
    return dokumentVorlage -> hasTemplateBekanntmachungWahlergebnis(dokumentVorlageArt, dokumentVorlage);
  }

  protected boolean hasTemplateBekanntmachungWahlergebnis(DokumentVorlageArt dokumentVorlageArt, DokumentVorlage dokumentVorlage) {
    return hasDateiImportAndTemplate(DefaultErgebnisdokumentTyp.BEKANNTMACHUNG_WAHLERGEBNIS, dokumentVorlageArt, dokumentVorlage);
  }

  public Predicate<DokumentVorlage> matchesDokumentVorlageWahlausschussNiederschrift(DokumentVorlageArt dokumentVorlageArt) {
    return dokumentVorlage -> hasTemplateWahlausschussNiederschrift(dokumentVorlageArt, dokumentVorlage) && !hasInfixSeitenartOrStimmenart(dokumentVorlage);
  }

  protected boolean hasTemplateWahlausschussNiederschrift(DokumentVorlageArt dokumentVorlageArt, DokumentVorlage dokumentVorlage) {
    return hasDateiImportAndTemplate(DefaultErgebnisdokumentTyp.WAHLAUSSCHUSS_NIEDERSCHRIFT, dokumentVorlageArt, dokumentVorlage);
  }

  protected boolean hasDateiImportAndTemplate(DokumentBulkExportSearchEntryTemplate dokumentBulkExportSearchEntryTemplate, DokumentVorlageArt dokumentVorlageArt, DokumentVorlage dokumentVorlage) {
    return existsDateiImport(dokumentVorlage) && hasDokumentVorlageArt(dokumentVorlage, dokumentVorlageArt)
        && hasInfix(dokumentVorlage, getBezeichnung(dokumentBulkExportSearchEntryTemplate, dokumentVorlage));
  }

  protected boolean hasInfixSeitenartOrStimmenartOrGebietsart(DokumentVorlage dokumentVorlage) {
    return hasInfixSeitenartOrStimmenart(dokumentVorlage) || hasAnyInfixGebietsart(dokumentVorlage);
  }

  protected boolean hasAnyInfixGebietsart(DokumentVorlage dokumentVorlage) {
    return hasInfixGebietsart(dokumentVorlage, Verwaltungsart.KREIS) || hasInfixGebietsart(dokumentVorlage, Verwaltungsart.GEMEINDE);
  }

  private boolean hasInfixGebietsart(DokumentVorlage dokumentVorlage, Verwaltungsart gebietsart) {
    return hasInfix(dokumentVorlage, messages.lokalisiere(gebietsart));
  }

  protected boolean hasInfixSeitenartOrStimmenart(DokumentVorlage dokumentVorlage) {
    return hasAnyInfixSeite(dokumentVorlage) || hasAnyInfixStimmenart(dokumentVorlage);
  }

  private boolean hasAnyInfixSeite(DokumentVorlage dokumentVorlage) {
    return hasInfixErsteSeite(dokumentVorlage) || hasInfixWeitereSeiten(dokumentVorlage);
  }

  protected boolean hasInfixErsteSeite(DokumentVorlage dokumentVorlage) {
    return hasInfix(dokumentVorlage, DOKUMENT_VORLAGE_NAME_INFIX_SEITENART_ERSTE_SEITE);
  }

  protected boolean hasInfixWeitereSeiten(DokumentVorlage dokumentVorlage) {
    return hasInfix(dokumentVorlage, DOKUMENT_VORLAGE_NAME_INFIX_SEITENART_WEITERE_SEITEN);
  }

  protected boolean hasAnyInfixStimmenart(DokumentVorlage dokumentVorlage) {
    return hasInfixStimmen(dokumentVorlage) || hasInfixDirektstimmen(dokumentVorlage) || hasInfixListenstimmen(dokumentVorlage);
  }

  private boolean hasInfixStimmzettel(DokumentVorlage dokumentVorlage) {
    return hasInfix(dokumentVorlage, DOKUMENT_VORLAGE_NAME_INFIX_STIMMENART_STIMMZETTEL);
  }

  private boolean hasInfixStimmen(DokumentVorlage dokumentVorlage) {
    return hasInfix(dokumentVorlage, DOKUMENT_VORLAGE_NAME_INFIX_STIMMENART_STIMMEN) && !(hasInfixDirektstimmen(dokumentVorlage) || hasInfixListenstimmen(dokumentVorlage));
  }

  private boolean hasInfixDirektstimmen(DokumentVorlage dokumentVorlage) {
    return hasInfix(dokumentVorlage, DOKUMENT_VORLAGE_NAME_INFIX_STIMMENART_DIREKTSTIMMEN);
  }

  private boolean hasInfixListenstimmen(DokumentVorlage dokumentVorlage) {
    return hasInfix(dokumentVorlage, DOKUMENT_VORLAGE_NAME_INFIX_STIMMENART_LISTENSTIMMEN);
  }

  private boolean hasDokumentVorlageArt(DokumentVorlage dokumentVorlage, DokumentVorlageArt dokumentVorlageArt) {
    return dokumentVorlageArt.equals(dokumentVorlage.getDokumentVorlageArt());
  }

  protected boolean hasPrefix(DokumentVorlage dokumentVorlage, String prefix) {
    return dokumentVorlage.matchesName(prefix, StringUtils::startsWithIgnoreCase);
  }

  protected boolean hasInfix(DokumentVorlage dokumentVorlage, String infix) {
    return dokumentVorlage.matchesName(infix);
  }

  protected String getBezeichnung(DokumentBulkExportSearchEntryTemplate dokumentBulkExportSearchEntryTemplate, DokumentVorlage dokumentVorlage) {
    return dokumentBulkExportSearchEntryTemplate.getBezeichnungDokumentVorlage(dokumentVorlage.getWahl(), dokumentVorlage.getWahltermin(), messages);
  }

  private boolean existsDateiImport(DokumentVorlage dokumentVorlage) {
    return dokumentVorlage != null && dokumentVorlage.getDateiImport() != null;
  }
}
