
package de.ivu.elect.business.konfiguration.entity;

import de.ivu.elect.business.email.entity.EmailConnectionEncryptionType;
import de.ivu.elect.business.internet.control.InternetPreasentationTypValidator;
import de.ivu.elect.business.internet.entity.InternetPraesentationTyp;
import de.ivu.elect.business.praesentation.entity.PraesentationUploadArt;
import de.ivu.elect.business.praesentation.entity.PresentationServletStatus;
import de.ivu.elect.business.replikation.entity.ReplikationArchiveEinstellung;
import de.ivu.elect.business.replikation.entity.ReplikationEinstellung;
import de.ivu.elect.business.security.Customer;
import de.ivu.elect.business.system.entity.HttpSessionTracking;
import de.ivu.elect.business.system.entity.SystemCheckStatus;

import javax.faces.validator.LongRangeValidator;
import javax.faces.validator.RequiredValidator;
import javax.faces.validator.Validator;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

import static de.ivu.elect.business.konfiguration.entity.CustomParameterKategorie.WES;
import static de.ivu.elect.business.konfiguration.entity.CustomParameterKategorie.*;
import static de.ivu.elect.business.konfiguration.entity.CustomParameterWertTyp.*;
import static de.ivu.elect.business.security.Customer.*;
import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;

/**
 * Enums für Systemparameter
 * <p>
 * Mandantenparameter nach MandantKonfigurationWerte
 */
public enum ElectKonfigurationWerte implements ElectSystemMandantKonfigurationWerte {


  SYSTEM_ID(SYSTEM, VOID, MINIMAL),

  ELECT_COMMON_DATEI_ABLAGE_VERZEICHNIS_PFAD(SYSTEM, VERZEICHNIS_BESCHREIBBAR_ABLAGE_VERZEICHNIS, MINIMAL),

  ELECT_COMMON_DATEI_CLEANUP_AKTIVIERT(DATEI_CLEANUP, BOOLEAN, MINIMAL),
  ELECT_COMMON_DATEI_CLEANUP_CRON_TIMER(DATEI_CLEANUP, CRONTAB, MINIMAL),
  ELECT_COMMON_DATEI_CLEANUP_MS_BEFORE_RECYLE(DATEI_CLEANUP, LONG, MINIMAL),
  ELECT_COMMON_DATEI_CLEANUP_MAX_EXPORT_COUNT(DATEI_CLEANUP, LONG, MINIMAL),
  ELECT_COMMON_DATEI_CLEANUP_MAX_IMPORT_COUNT(DATEI_CLEANUP, LONG, MINIMAL),
  ELECT_COMMON_DATEI_CLEANUP_DAYS_IN_RECYCLE_BIN(DATEI_CLEANUP, LONG, MINIMAL),

  ELECT_COMMON_PROTOKOLL_CLEANUP_CRON_TIMER(SYSTEM, CRONTAB, MINIMAL),

  ELECT_COMMON_SYSTEM_CHECK_STATUS(SYSTEM, ENUM, SystemCheckStatus.class, MINIMAL),
  ELECT_COMMON_LOKALISIERUNG_SAMMELN(SYSTEM, BOOLEAN, MINIMAL),

  ELECT_COMMON_DB_CLEANUP_PERSONENDATEN_NAMEN_NORMALISIERT_AKTUALISIEREN(SYSTEM, BOOLEAN, COMMON),
  ELECT_COMMON_TEMP_VERZEICHNIS_PFAD(SYSTEM, VERZEICHNIS_BESCHREIBBAR, MINIMAL),
  ELECT_COMMON_RANDOM_GENERATOR_SECURE(SYSTEM, BOOLEAN, MINIMAL),

  DEEP_LINKING_ENABLED(HTTP, BOOLEAN, MINIMAL),
  HTTP_SESSION_TRACKING_MODE(HTTP, ENUM, HttpSessionTracking.class, MINIMAL),
  HTTP_SESSION_COOKIE_CONFIG_HTTP_ONLY(HTTP, BOOLEAN, MINIMAL), // WASDE-1547
  HTTP_SESSION_COOKIE_CONFIG_SECURE(HTTP, BOOLEAN, MINIMAL), // WASDE-1546

  // ELECT-8017
  // siehe auch: HttpHeaderKonfigurationHelper
  HTTP_HEADER_X_UA_COMPATIBLE(HTTP, STRING, MINIMAL),
  HTTP_HEADER_X_CONTENT_TYPE_OPTIONS(HTTP, STRING, MINIMAL),
  HTTP_HEADER_X_FRAME_OPTIONS(HTTP, STRING, MINIMAL),
  HTTP_HEADER_X_XSS_PROTECTION(HTTP, STRING, MINIMAL),
  HTTP_HEADER_X_POWERED_BY(HTTP, STRING, MINIMAL),
  HTTP_HEADER_SERVER(HTTP, STRING, MINIMAL),
  HTTP_HEADER_STRICT_TRANSPORT_SECURITY(HTTP, STRING, MINIMAL),
  HTTP_HEADER_CONTENT_SECURITY_POLICY(HTTP, STRING, MINIMAL),
  HTTP_HEADER_ADDITIONAL(HTTP, STRING, MINIMAL),

  HTTP_BASIS_URL(HTTP, STRING, MINIMAL),

  HIBERNATE_STATISTIKEN_AKTIVIEREN(SYSTEM, BOOLEAN, MINIMAL),
  HIBERNATE_STATISTIKEN_LOG_INTERVAL_CRONTAB(SYSTEM, CRONTAB, MINIMAL),

  PERFORMANCE_STATISTIKEN_AKTIVIEREN(SYSTEM, BOOLEAN, MINIMAL),
  PERFORMANCE_STATISTIKEN_DETAILLIERTE_LOGAUSGABEN(SYSTEM, BOOLEAN, MINIMAL),
  PERFORMANCE_STATISTIKEN_LOG_INTERVALL_CRONTAB(SYSTEM, CRONTAB, MINIMAL),

  SYSTEM_INFO_LOG_INTERVALL_CRONTAB(SYSTEM, CRONTAB, MINIMAL),


  DASHBOARD_NEWS_HEADER(SYSTEM, STRING, DASHBOARD_NEWS),
  DASHBOARD_NEWS_MESSAGE_SNIPPET(SYSTEM, STRING, DASHBOARD_NEWS),
  DASHBOARD_NEWS_IFRAME_HOST(SYSTEM, STRING, DASHBOARD_NEWS),


  MAIL_JNDI(MAIL, STRING, MAIL_SUPPORT),
  MAIL_HOST(MAIL, STRING, MAIL_SUPPORT),
  MAIL_PORT(MAIL, STRING, MAIL_SUPPORT),
  MAIL_AUTHENTICATION_ENABLED(MAIL, BOOLEAN, MAIL_SUPPORT),
  MAIL_USERNAME(MAIL, STRING, MAIL_SUPPORT),
  MAIL_PASSWORD(MAIL, STRING_SECRET, MAIL_SUPPORT),
  MAIL_CONNECTION_ENCRYPTION_MODE(MAIL, ENUM, EmailConnectionEncryptionType.class, MAIL_SUPPORT),
  MAIL_CHARSET_BODY(MAIL, STRING, MAIL_SUPPORT),
  MAIL_CHARSET_MIME(MAIL, STRING, MAIL_SUPPORT),

  OPEN_OFFICE_PATH(DOKUMENTENERZEUGUNG, VERZEICHNIS, DOKUMENTENGENERATOR),
  OPEN_OFFICE_DEFAULT_PORT_NUMBER(DOKUMENTENERZEUGUNG, INTEGER, DOKUMENTENGENERATOR),
  OPEN_OFFICE_ADDITIONAL_PORT_NUMBERS(DOKUMENTENERZEUGUNG, STRING, DOKUMENTENGENERATOR),
  OPEN_OFFICE_WORKING_DIR(DOKUMENTENERZEUGUNG, VERZEICHNIS_BESCHREIBBAR, DOKUMENTENGENERATOR),
  OPEN_OFFICE_TEMPLATE_PROFILE_DIR(DOKUMENTENERZEUGUNG, VERZEICHNIS_BESCHREIBBAR, DOKUMENTENGENERATOR),
  OPEN_OFFICE_KILL_EXISTING_PROCESS(DOKUMENTENERZEUGUNG, BOOLEAN, DOKUMENTENGENERATOR),
  OPEN_OFFICE_DISABLE_OPENGL(DOKUMENTENERZEUGUNG, BOOLEAN, DOKUMENTENGENERATOR),
  OPEN_OFFICE_PROCESS_TIMEOUT_IN_MS(DOKUMENTENERZEUGUNG, LONG, DOKUMENTENGENERATOR),
  OPEN_OFFICE_PROCESS_RETRY_INTERVAL_IN_MS(DOKUMENTENERZEUGUNG, LONG, DOKUMENTENGENERATOR),
  OPEN_OFFICE_TASK_EXECUTION_TIMEOUT_IN_MS(DOKUMENTENERZEUGUNG, LONG, DOKUMENTENGENERATOR),
  OPEN_OFFICE_TASK_QUEUE_TIMEOUT_IN_MS(DOKUMENTENERZEUGUNG, LONG, DOKUMENTENGENERATOR),
  OPEN_OFFICE_MAX_TASKS_PER_PROCESS(DOKUMENTENERZEUGUNG, LONG, DOKUMENTENGENERATOR),
  OPEN_OFFICE_STARTUP(DOKUMENTENERZEUGUNG, ENUM, OpenOfficeStartup.class, DOKUMENTENGENERATOR),

  @Deprecated
  // MUC als Suffix, nicht als Präfix   (Wegen Sortierung an der Oberfläche...)
  MUC_NAT_SEC_SERVICE_URL(AUTHENTIFIZIERUNG, STRING, MUC_BASE), // Zum Testen lokal: http://localhost:8080/natsec-mock/IDLGENPort
  @Deprecated
  // MUC als Suffix, nicht als Präfix (Wegen Sortierung an der Oberfläche...)
  MUC_NAT_SEC_PROJECT_ID(AUTHENTIFIZIERUNG, STRING, MUC_BASE),

  PRAESENTATION_EXPORT_INTERNET_AKTIVIERT(PRAESENTATION, BOOLEAN, DESTATIS_WAS::equals, WAS),
  PRAESENTATION_EXPORT_INTERNET_MINIMALE_PAUSE_IN_SEKUNDEN(PRAESENTATION, LONG, DESTATIS_WAS::equals, WAS),
  PRAESENTATION_TYP(PRAESENTATION, ENUM, InternetPraesentationTyp.class, singletonList(new InternetPreasentationTypValidator()), CORE),
  PRAESENTATION_EXPORT_UPLOAD_ART(PRAESENTATION, ENUM, PraesentationUploadArt.class, DESTATIS_WAS::equals, WAS),
  PRAESENTATION_SERVLET_STATUS(PRAESENTATION, ENUM, PresentationServletStatus.class, WAS),

  // Systemweit reciht, da einzelne Mandanten sowieso kein Zugriff auf Verzeichnisse des Servers haben
  PRAESENTATION_EXPORT_ABLAGEVERZEICHNIS(PRAESENTATION, VERZEICHNIS_BESCHREIBBAR, DESTATIS_WAS::equals, WAS),
  PRAESENTATION_EXPORT_ALS_ZIP_DATEI(PRAESENTATION, BOOLEAN, DESTATIS_WAS::equals, WAS),


  @Deprecated // DO NOT USE ELECT-6191
  STIMMEINGABE_ABLAGEVERZEICHNIS_F_DATEIEN(STIMMEINGABE, VERZEICHNIS_BESCHREIBBAR, TEST /* ELECT-6191 */),

  STIMMEINGABE_IMPORTVERZEICHNIS(STIMMEINGABE, VERZEICHNIS, WAS),
  STIMMEINGABE_IMPORT_CRONTAB(STIMMEINGABE, CRONTAB, WAS),
  STIMMEINGABE_IMPORT_EINGANGSSEQUENZNUMMER(STIMMEINGABE, LONG, WAS),
  STIMMEINGABE_LETZTE_EINGANGSSEQUENZNUMMER_LOESCHEN(STIMMEINGABE, VOID, WAS),

  EXTERNER_ABGLEICH_CRONTAB(PERSONENREGISTER, CRONTAB, WUS),
  EXTERNER_ABGLEICH_EMAIL_EMPFAENGER(PERSONENREGISTER, STRING, WUS),

  WAHLHELFER_AUS_EXTERNER_QUELLE_IMPORTIEREN_CRONTAB(WAHLHELFER_IMPORT, CRONTAB, WOS),

  WAHLHELFER_EXTERNE_QUELLE_LETZTE_ID_DD(WAHLHELFER_IMPORT, LONG, DD_WOS),
  WAHLHELFER_EXTERNE_QUELLE_BEREITSCHAFT_1_DD(WAHLHELFER_IMPORT, STRING, DD_WOS),
  WAHLHELFER_EXTERNE_QUELLE_BEREITSCHAFT_2_DD(WAHLHELFER_IMPORT, STRING, DD_WOS),
  WAHLHELFER_EXTERNE_QUELLE_BEREITSCHAFT_3_DD(WAHLHELFER_IMPORT, STRING, DD_WOS),

  LOGIN_MANDANT_AUSWAHL_ART(AUTHENTIFIZIERUNG, ENUM, LoginMandantAuswahlArt.class, MINIMAL),
  SINGLE_SIGN_ON_AKTIVIERT(AUTHENTIFIZIERUNG, BOOLEAN, ACTIVE_DIRECTORY_SUPPORT),
  SINGLE_SIGN_ON_LOCALHOST_ERLAUBT(AUTHENTIFIZIERUNG, BOOLEAN, ACTIVE_DIRECTORY_SUPPORT),
  SINGLE_SIGN_ON_KRB5_CONF_PFAD(AUTHENTIFIZIERUNG, STRING, ACTIVE_DIRECTORY_SUPPORT),
  SINGLE_SIGN_ON_PRE_AUTH_BENUTZER(AUTHENTIFIZIERUNG, STRING, ACTIVE_DIRECTORY_SUPPORT),
  SINGLE_SIGN_ON_PRE_AUTH_PASSWORT(AUTHENTIFIZIERUNG, STRING_SECRET, ACTIVE_DIRECTORY_SUPPORT),

  BEWERBERTABELLEN_ABLAGE_VERZEICHNIS_PFAD(SONSTIGES, VERZEICHNIS_BESCHREIBBAR, DESTATIS_WUS),
  BEWERBERTABELLEN_EXPORT_ABLAGE_VERZEICHNIS_PFAD(SONSTIGES, VERZEICHNIS_BESCHREIBBAR, DESTATIS_WUS),

  REPLIKATION_EINSTELLUNG(REPLIKATION, ENUM, ReplikationEinstellung.class, REPLIKATION_SUPPORT),
  REPLIKATION_VERZEICHNIS(REPLIKATION, VERZEICHNIS_BESCHREIBBAR, REPLIKATION_SUPPORT),
  REPLIKATION_CRONTAB(REPLIKATION, CRONTAB, REPLIKATION_SUPPORT),
  REPLIKATION_FORTLAUFENDE_NUMMER(REPLIKATION, LONG, singletonList(new LongRangeValidator(Long.MAX_VALUE, 0L)), REPLIKATION_SUPPORT),
  REPLIKATION_ARCHIVE_SETTING(REPLIKATION, ENUM, ReplikationArchiveEinstellung.class, REPLIKATION_SUPPORT),

  REPLIKATION_DOWNLOAD_URL(REPLIKATION, STRING, REPLIKATION_SUPPORT),
  REPLIKATION_DOWNLOAD_TIMEOUT_IN_SECONDS(REPLIKATION, LONG,
          asList(new RequiredValidator (), new LongRangeValidator(ElectKonfigurationWerte.MAX_REPLIKATION_DOWNLOAD_TIMEOUT_IN_MINUTES, ElectKonfigurationWerte.MIN_REPLIKATION_DOWNLOAD_TIMEOUT_IN_MINUTES)), REPLIKATION_SUPPORT),
  REPLIKATION_DOWNLOAD_SECRET(REPLIKATION, STRING_SECRET, REPLIKATION_SUPPORT),

  MELDEDATEN_EINTRAG_PAKET_BEARBEITEN_BACKGROUND_SLOTS(SONSTIGES, LONG,
          asList(new RequiredValidator (), new LongRangeValidator(ElectKonfigurationWerte.MAX_MELDEDATEN_EINTRAG_PAKET_BEARBEITEN_BACKGROUND_SLOTS, ElectKonfigurationWerte.MIN_MELDEDATEN_EINTRAG_PAKET_BEARBEITEN_BACKGROUND_SLOTS)),
      WVZ),
  MELDEDATEN_INITIALER_IMPORT_VERZEICHNIS(PERSONENREGISTER, VOID /* siehe de.ivu.elect.business.meldedaten.boundary.MeldedatenEintragImportEchtdaten */, WVZ),
  MELDEDATEN_INITIALER_IMPORT_ZEITPUNKT_DATENSTAND(PERSONENREGISTER, VOID/*
                                                                          * siehe de.ivu.elect.business.meldedaten.boundary.MeldedatenEintragImportEchtdaten
                                                                          */, singletonList(new RequiredValidator()), WVZ),
  MUC_MELDEDATEN_INITIALER_IMPORT_ABRUF_ANZAHL_WOHNUNGEN_VORHANDEN(PERSONENREGISTER, LONG, MUC_WVZ),
  MUC_MELDEDATEN_INITIALER_IMPORT_ABRUF_WOHNT_WENIGER_MONATE_IN_MUC(PERSONENREGISTER, LONG, MUC_WVZ),
  MUC_MELDEDATEN_INITIALER_IMPORT_ABRUF_NUR_ANZAHL_MONATE_BEKANNT_MIT_ALTEM_OM(PERSONENREGISTER, LONG, MUC_WVZ),

  MELDEDATEN_INITIALER_IMPORT_ZEITPUNKT_DATENSTAND_ENDE_ZEITPUNKT_MANUELL(PERSONENREGISTER, TIMESTAMP, WVZ), // ELECTMUC-1835

  MELDEDATEN_AENDERUNGSLAUF_CRONTAB(PERSONENREGISTER, CRONTAB, WVZ),
  MELDEDATEN_AENDERUNG_VERARBEITEN_BATCH_SIZE(PERSONENREGISTER, LONG, asList(new RequiredValidator (), new LongRangeValidator(Integer.MAX_VALUE, 1L)), WVZ),

  WAEHLERVERZEICHNIS_AKTUALISIEREN_BATCH_SIZE(SONSTIGES, LONG, asList(new RequiredValidator (), new LongRangeValidator(Integer.MAX_VALUE, 1L)), WVZ),
  WAHLSCHEINANTRAG_ZUORDNEN_BATCH_SIZE(SONSTIGES, LONG, asList(new RequiredValidator (), new LongRangeValidator(Integer.MAX_VALUE, 1L)), WVZ),
  WAHLSCHEINANTRAG_BERECHTIGUNG_PRUEFEN_BATCH_SIZE(SONSTIGES, LONG, asList(new RequiredValidator (), new LongRangeValidator(Integer.MAX_VALUE, 1L)), WVZ),

  WVZ_PERSONENREGISTER_SUCHE_SERVICE_URL(PERSONENREGISTER, STRING, singletonList(new RequiredValidator()), WVZ),
  WVZ_PERSONENREGISTER_SUCHE_SERVICE_LOGGING_ENABLED(PERSONENREGISTER, BOOLEAN, WVZ),
  WVZ_PERSONENREGISTER_SUCHE_SERVICE_WSS_ENABLED_MUC(PERSONENREGISTER, BOOLEAN, MUC_WVZ),
  WVZ_PERSONENREGISTER_SUCHE_SERVICE_WSS_USERNAME_MUC(PERSONENREGISTER, STRING, MUC_WVZ),
  WVZ_PERSONENREGISTER_SUCHE_SERVICE_WSS_PASSWORD_MUC(PERSONENREGISTER, STRING_SECRET, MUC_WVZ),

  WVZ_MELDEDATENAENDERUNGEN_SUCHE_SERVICE_URL(PERSONENREGISTER, STRING, singletonList(new RequiredValidator()), WVZ),
  WVZ_MELDEDATENAENDERUNGEN_SUCHE_SERVICE_LOGGING_ENABLED(PERSONENREGISTER, BOOLEAN, WVZ),
  WVZ_MELDEDATENAENDERUNGEN_SUCHE_SERVICE_WSS_ENABLED_MUC(PERSONENREGISTER, BOOLEAN, MUC_WVZ),
  WVZ_MELDEDATENAENDERUNGEN_SUCHE_SERVICE_WSS_USERNAME_MUC(PERSONENREGISTER, STRING, MUC_WVZ),
  WVZ_MELDEDATENAENDERUNGEN_SUCHE_SERVICE_WSS_PASSWORD_MUC(PERSONENREGISTER, STRING_SECRET, MUC_WVZ),

  MUC_WVZ_MELDEDATEN_STRASSENNAME_KURZ_AUS_ANSCHRIFTEN_ERGAENZEN(PERSONENREGISTER, BOOLEAN, MUC_WVZ), // ELECTMUC-2393

  // ELECTMUC-2762
  NIEDERSCHRIFT_STATUS_AENDERUNG_VALUES_RAUM_ERGEBNISERFASSUNG(SONSTIGES, STRING, MUC_WAS),
  NIEDERSCHRIFT_STATUS_AENDERUNG_VALUES_RAUM_WEITERE(SONSTIGES, STRING, MUC_WAS),

  NIEDERSCHRIFT_STATUS_AENDERUNG_RAUM_WAHLLOKALSYSTEM(SONSTIGES, STRING, MUC_WAS),
  NIEDERSCHRIFT_STATUS_AENDERUNG_BESITZER_WAHLLOKALSYSTEM(SONSTIGES, STRING, MUC_WAS),

  WVP_API_URL(WVP, STRING, WUS_INTERFACES_WVP),
  WVP_KEYSTORE_PATH(WVP, STRING, WUS_INTERFACES_WVP),
  WVP_KEYSTORE_PASSWORD(WVP, STRING_SECRET, WUS_INTERFACES_WVP),
  WVP_ZERTIFIKAT_PATH(WVP, STRING, WUS_INTERFACES_WVP),
  WVP_BENUTZERKONTEN_PAPIERKORB_AUFBEWAHRUNG_IN_TAGEN(WVP, LONG, WUS_INTERFACES_WVP),
  WVP_BENUTZERKONTEN_CLEANUP_CRON_TIMER(WVP, CRONTAB, WUS_INTERFACES_WVP),

  PERSONEN_PRUEFUNG_MAX_ANZAHL_PRUEFUNGEN_PRO_TRANSAKTION(SONSTIGES, LONG, asList(new RequiredValidator (), new LongRangeValidator(Integer.MAX_VALUE, 1L)), COMMON),

  WAHLEXPORT_CRONTAB(WAHL_EXPORT, CRONTAB, WOS, WAS),
  WAHLEXPORT_PFAD(WAHL_EXPORT, VERZEICHNIS_BESCHREIBBAR, WOS, WAS),
  WAHLEXPORT_DATUM(WAHL_EXPORT, DATE, WOS, WAS),
  WAHLEXPORT_AKTIVIERT(WAHL_EXPORT, BOOLEAN, WOS, WAS),

  WES_TEMPLATE_ABLAGEPFAD(WES, VERZEICHNIS, WES_UNTERSTUETZUNG),
  WES_EXPORT_MAX_ANZAHL(WES, LONG, WES_UNTERSTUETZUNG),

  MUC_WLS_CACHE_FUER_IDS_VERWENDEN(WAHLLOKALSYSTEM, BOOLEAN, MUC_WOS, MUC_WAS),

  MEMORY_GC_CRONTAB(SYSTEM, CRONTAB, MINIMAL),
  MEMORY_GC_LOGGING_ENABLED(SYSTEM, BOOLEAN, MINIMAL),
  MEMORY_GC_ANZAHL_EINTRAEGE(SYSTEM, LONG, asList(new RequiredValidator (), new LongRangeValidator(10000L, 5L)), MINIMAL);

  private static final long MIN_MELDEDATEN_EINTRAG_PAKET_BEARBEITEN_BACKGROUND_SLOTS = 1;

  private static final long MAX_MELDEDATEN_EINTRAG_PAKET_BEARBEITEN_BACKGROUND_SLOTS = 64;

  private static final long MAX_REPLIKATION_DOWNLOAD_TIMEOUT_IN_MINUTES = 3600; // 1 Stunde

  private static final long MIN_REPLIKATION_DOWNLOAD_TIMEOUT_IN_MINUTES = 1;

  private final List<Customer> customers;

  private final Predicate<Customer> customersExcludedFilter;

  private final CustomParameterKategorie kategorie;

  private final CustomParameterWertTyp wertTyp;

  private final List<Validator> wertValidators;

  private final Supplier<List<String>> wertStringValues;

  private final Supplier<Function<String, String>> wertStringValueToLabelFct;

  private final Class< ? extends Enum< ? >> wertEnumClass;

  private final Class<? extends CustomParameterFilter<Konfiguration, ? extends Enum<?>>> filter;


  ElectKonfigurationWerte(CustomParameterKategorie kategorie, CustomParameterWertTyp wertTyp, Customer... customers) {
    this(kategorie, wertTyp, c -> false, customers);
  }

  ElectKonfigurationWerte(CustomParameterKategorie kategorie, CustomParameterWertTyp wertTyp, Predicate<Customer> customersExcludedFilter, Customer... customers) {
    this(kategorie, wertTyp, emptyList(), customersExcludedFilter, customers);
  }

  ElectKonfigurationWerte(CustomParameterKategorie kategorie, CustomParameterWertTyp wertTyp, List<Validator> wertValidators, Customer... customers) {
    this(kategorie, wertTyp, wertValidators, c -> false, customers);
  }

  ElectKonfigurationWerte(CustomParameterKategorie kategorie, CustomParameterWertTyp wertTyp, List<Validator> wertValidators, Predicate<Customer> customersExcludedFilter, Customer... customers) {
    this(kategorie, wertTyp, null, null, wertValidators, customersExcludedFilter, customers);
  }

  <E extends Enum<?>> ElectKonfigurationWerte(CustomParameterKategorie kategorie, CustomParameterWertTyp wertTyp, Class< E> wertEnumClass, Customer... customers) {
    this(kategorie, wertTyp, wertEnumClass, c -> false, customers);
  }

  <E extends Enum<?>> ElectKonfigurationWerte(CustomParameterKategorie kategorie, CustomParameterWertTyp wertTyp, Class<E> wertEnumClass, Predicate<Customer> customersExcludedFilter,
      Customer... customers) {
    this(kategorie, wertTyp, wertEnumClass, null, emptyList(), customersExcludedFilter, customers);
  }

  <E extends Enum<?>> ElectKonfigurationWerte(CustomParameterKategorie kategorie, CustomParameterWertTyp wertTyp, Class<E> wertEnumClass, List<Validator> wertValidators, Customer... customers) {
    this(kategorie, wertTyp, wertEnumClass, null, wertValidators, c -> false, customers);
  }

  <E extends Enum<?>> ElectKonfigurationWerte(CustomParameterKategorie kategorie, CustomParameterWertTyp wertTyp, Class<E> wertEnumClass, Class<? extends CustomParameterFilter<Konfiguration, E>> filter,
      List<Validator> wertValidators, Predicate<Customer> customersExcludedFilter, Customer... customers) {
    this(kategorie, wertTyp, wertEnumClass, filter, Collections::emptyList, Function::identity, wertValidators, customersExcludedFilter, customers);
  }

  ElectKonfigurationWerte(CustomParameterKategorie kategorie, CustomParameterWertTyp wertTyp, Supplier<List<String>> wertStringValues, Supplier<Function<String, String>> wertStringValueToLabelFct,
      List<Validator> wertValidators, Customer... customers) {
    this(kategorie, wertTyp, null, null, wertStringValues, wertStringValueToLabelFct, wertValidators, customers);
  }

  <E extends Enum<?>> ElectKonfigurationWerte(CustomParameterKategorie kategorie, CustomParameterWertTyp wertTyp, Class< E> wertEnumClass, Class<? extends CustomParameterFilter<Konfiguration, E>> filter,
      Supplier<List<String>> wertStringValues, Supplier<Function<String, String>> wertStringValueToLabelFct, List<Validator> wertValidators, Customer... customers) {
    this(kategorie, wertTyp, wertEnumClass, filter, wertStringValues, wertStringValueToLabelFct, wertValidators, x -> false, customers);
  }

  <E extends Enum<?>> ElectKonfigurationWerte(CustomParameterKategorie kategorie, CustomParameterWertTyp wertTyp, Class<E> wertEnumClass,
                          Class<? extends CustomParameterFilter<Konfiguration, E>> filter,
                          Supplier<List<String>> wertStringValues, Supplier<Function<String, String>> wertStringValueToLabelFct, List<Validator> wertValidators, Predicate<Customer> customersExcludedFilter,
                          Customer... customers) {
    this.customers = asList(customers);
    this.customersExcludedFilter = customersExcludedFilter;

    this.kategorie = kategorie;

    this.wertTyp = wertTyp;
    this.wertValidators = wertValidators;

    this.wertStringValues = wertStringValues;
    this.wertStringValueToLabelFct = wertStringValueToLabelFct;

    this.wertEnumClass = wertEnumClass;
    this.filter = filter;
  }

  @Override
  public Supplier<List<String>> getWertStringValues() {
    return wertStringValues;
  }

  @Override
  public Supplier<Function<String, String>> getWertStringValueToLabelFct() {
    return wertStringValueToLabelFct;
  }

  @Override
  public List<Customer> getCustomers() {
    return customers;
  }

  @Override
  public CustomParameterKategorie getKategorie() {
    return kategorie;
  }

  @Override
  public String getKey() {
    return name();
  }

  @Override
  public CustomParameterWertTyp getWertTyp() {
    return wertTyp;
  }

  @Override
  public Class< ? extends Enum< ? >> getWertEnumClass() {
    return wertEnumClass;
  }

  @Override
  public List<Validator> getWertValidators() {
    return wertValidators;
  }

  @Override
  public boolean isCustomerExcluded(Customer customer) {
    return customersExcludedFilter.test(customer);
  }

  @Override
  public KonfigurationMandantArt getKonfigurationMandantArt() {
    return KonfigurationMandantArt.SYSTEM_PARAMETER;
  }

  static ElectKonfigurationWerte bestimmeKeyEnum(String keyValue) {
    if (keyValue.contains(".")) {
      return ElectKonfigurationWerte.valueOf(keyValue.substring(0, keyValue.indexOf(".")));
    } else {
      return ElectKonfigurationWerte.valueOf(keyValue);
    }
  }

  @Override
  public Class<? extends CustomParameterFilter<Konfiguration, ? extends Enum<?>>> getFilter() {
    return filter;
  }
}
