package de.ivu.elect.presentation.gebietsbaum.form;

import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;

import javax.faces.convert.Converter;

import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.jee.faces.EntityConverter;
import de.ivu.elect.jee.presentation.dynamicform.AbstractPickListProperty;
import de.ivu.elect.presentation.gebietsbaum.GebietNummerFormatter;

public class GebietePicklistProperty<G extends Gebiet> extends AbstractPickListProperty<G> {

  private final List<G> alleGebiete;

  private final Function<G, String> mappingFct;

  private final Set<String> zugeordneteGebiete;

  private final String label;

  private final String quelleLabel;

  private final String zugeordnetLabel;

  private final Function<Gebiet, String> gebietNummerFormatter;

  private final Consumer<Set<String>> zugeordnetConsumer;

  private final boolean defaultRequired;

  public GebietePicklistProperty(List<G> alleGebiete, Function<G, String> mappingFct, Set<String> zugeordneteGebiete, String label, String quelleLabel, String zugeordnetLabel, GebietNummerFormatter gebietNummerFormatter, Consumer<Set<String>> zugeordnetConsumer) {
    this(alleGebiete, mappingFct, zugeordneteGebiete, label, quelleLabel, zugeordnetLabel, gebietNummerFormatter::getDarstellung, zugeordnetConsumer, false);
  }

  public GebietePicklistProperty(List<G> alleGebiete, Function<G, String> mappingFct, Set<String> zugeordneteGebiete, String label, String quelleLabel, String zugeordnetLabel, Function<Gebiet, String> gebietNummerFormatter, Consumer<Set<String>> zugeordnetConsumer, boolean defaultRequired) {
    this.alleGebiete = alleGebiete;
    this.mappingFct = mappingFct;
    this.zugeordneteGebiete = zugeordneteGebiete;
    this.label = label;
    this.quelleLabel = quelleLabel;
    this.zugeordnetLabel = zugeordnetLabel;
    this.gebietNummerFormatter = gebietNummerFormatter;
    this.zugeordnetConsumer = zugeordnetConsumer;
    this.defaultRequired = defaultRequired;
  }

  @Override
  protected List<G> getZugeordneteElemente() {
    return alleGebiete.stream().filter(gebiet -> zugeordneteGebiete.contains(mappingFct.apply(gebiet))).collect(Collectors.toList());
  }

  @Override
  protected List<G> getVerfuegbareElemente() {
    return alleGebiete;
  }

  @Override
  protected void setzeZugeordneteElemente(List<G> list) {
    zugeordneteGebiete.clear();
    for (G gebiet : list) {
      zugeordneteGebiete.add(mappingFct.apply(gebiet));
    }
    zugeordnetConsumer.accept(zugeordneteGebiete);
  }

  public Set<String> getZugeordneteGebiete() {
    return zugeordneteGebiete;
  }

  @Override
  protected String getSourceCaptionMessageKey() {
    return quelleLabel;
  }

  @Override
  protected String getTargetCaptionMessageKey() {
    return zugeordnetLabel;
  }

  @Override
  public String getItemLabel(Gebiet gebiet) {
    return gebietNummerFormatter.apply(gebiet);
  }

  @Override
  public String getDefaultLabel() {
    return label;
  }

  @Override
  public boolean getDefaultRequired() {
    return defaultRequired;
  }

  @Override
  public Converter getDefaultConverter() {
    return EntityConverter.getInstance();
  }
}
