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

import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

import javax.faces.validator.LongRangeValidator;
import javax.faces.validator.Validator;

import de.ivu.elect.business.konfiguration.entity.CustomParameterFilter;
import de.ivu.elect.business.konfiguration.entity.CustomParameterKategorie;
import de.ivu.elect.business.konfiguration.entity.CustomParameterTemplate;
import de.ivu.elect.business.konfiguration.entity.CustomParameterWertTyp;
import de.ivu.elect.business.security.Customer;


import static de.ivu.elect.business.konfiguration.entity.CustomParameterKategorie.*;
import static de.ivu.elect.business.konfiguration.entity.CustomParameterWertTyp.ENUM;
import static de.ivu.elect.business.konfiguration.entity.CustomParameterWertTyp.LONG;
import static de.ivu.elect.business.security.Customer.MINIMAL;
import static de.ivu.elect.business.security.Customer.WOS;
import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;

// Cf. de.ivu.elect.business.konfiguration.entity.ElectKonfigurationWerte!
public enum BenutzerParameterWerte implements CustomParameterTemplate {

  ANZAHL_SUCHERGEBNISSE_PRO_SEITE(BENUTZER_SUCHEINSTELLUNGEN, LONG, asList(new LongRangeValidator(500L, 5L)), MINIMAL),
  POSITION_SUCHAKTIONEN(BENUTZER_SUCHEINSTELLUNGEN, ENUM, BenutzerEinstellungenSearchAction.class, MINIMAL),

  ANZUZEIGENDE_MELDUNGSARTEN(BENUTZER_BENACHRICHTIGUNG, ENUM, BenutzerEinstellungenMessageSeverity.class, MINIMAL),
  POPUP_MELDUNGEN_ENTFERNEN(BENUTZER_BENACHRICHTIGUNG, ENUM, BenutzerEinstellungenMessageStickiness.class, MINIMAL),
  MESSAGE_POSITION(BENUTZER_BENACHRICHTIGUNG, ENUM, BenutzerEinstellungenMessagePosition.class, MINIMAL),

  SUCHPARAMTER_SICHTBARKEIT(BENUTZER_SUCHEINSTELLUNGEN, ENUM, BenutzerSuchparameterEinstellung.class, MINIMAL),
  EDITOR_FELD_SICHTBARKEIT(BENUTZER_EDITOREINSTELLUNGEN, ENUM, BenutzerEditorFeldEinstellung.class, MINIMAL),

  WAHLHELFER_EINTEILEN_ANSICHT(BENUTZER_ANZEIGEEINSTELLUNGEN, ENUM, WahlhelferEinteilenAnsichtArt.class, WOS)

  ;

  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<BenutzerParameter, ? extends Enum<?>>> filter;


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

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

  <E extends Enum<?>> BenutzerParameterWerte(CustomParameterKategorie kategorie, CustomParameterWertTyp wertTyp, Class<E> wertEnumClass, Class<? extends CustomParameterFilter<BenutzerParameter, E>> filter,
                                             List<Validator> wertValidators, Customer... customers) {
    this(kategorie, wertTyp, wertEnumClass, filter, Collections::emptyList, Function::identity, wertValidators, c -> false, customers);
  }

  <E extends Enum<?>> BenutzerParameterWerte(CustomParameterKategorie kategorie, CustomParameterWertTyp wertTyp, Class<E> wertEnumClass, Class<? extends CustomParameterFilter<BenutzerParameter, 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;
  }

  public static boolean isGueltigerSchluesel(String schluessel) {
    try {
      return valueOf(schluessel) != null;
    } catch (Exception e) {
      return false;
    }
  }

  @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 Supplier<List<String>> getWertStringValues() {
    return wertStringValues;
  }

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

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

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

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