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

import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.inject.Inject;

import de.ivu.elect.business.person.entity.PersonenVerknuepfung;
import de.ivu.elect.business.person.entity.Personendaten;
import de.ivu.elect.business.person.entity.VerknuepfungsArt;

public abstract class AbstractVerknuepfungBestimmer<E extends Personendaten> {

  @Inject
  private transient PersonenVerknuepfungBerechner<E> personenVerknuepfungBerechner;

  public AbstractVerknuepfungBestimmer() {
    super();
  }

  public abstract VerknuepfungsArt getVerknuepfungsArt();

  /**
   * Bestimmt Verknüpfungen zwischen Personen mittels fachlicher Logik. Das stumpfe Berechnen findet im {@link PersonenVerknuepfungBerechner} statt
   */
  public List<PersonenVerknuepfung> bestimmeAnzulegendeVerknuepfungen(Collection< ? extends E> pruefmenge, Collection< ? extends E> vergleichsmenge) {
    Set<E> personen = new HashSet<>((pruefmenge.size() + vergleichsmenge.size()) * 2);
    personen.addAll(pruefmenge);
    personen.addAll(vergleichsmenge);

    return getPersonenVerknuepfungBerechner().bestimmeFehlendeVerknuepfungen(personen, getPersonenVergleichFunktion(), getFilter(pruefmenge, vergleichsmenge), getVerknuepfungsArt());
  }

  protected PersonenVerknuepfungBerechner<E> getPersonenVerknuepfungBerechner() {
    return personenVerknuepfungBerechner;
  }

  protected PersonenVerknuepfungFilter getFilter(Collection< ? extends E> pruefmenge, Collection< ? extends E> vergleichsmenge) {
    PersonenVerknuepfungFilter nurVerknuepfungenZwischenPruefmengeUndVergleichsmenge = new VerknuepfungenZwischenPruefmengeUndVergleichsmengeFilter<>(pruefmenge, vergleichsmenge);
    PersonenVerknuepfungFilter nurPersonenMitGleicherWahlOderWahltermin = new VerknuepfungenInnerhalbWahlOderWahlterminFilter();
    PersonenVerknuepfungFilter keineVerschiedenenVerknuepfungen = PersonenVerknuepfungFilter.AEHNLICHE_ODER_IDENTISCHE_VERKNUEPFUNGEN;

    return verknuepfung -> keineVerschiedenenVerknuepfungen.isAccept(verknuepfung) && nurVerknuepfungenZwischenPruefmengeUndVergleichsmenge.isAccept(verknuepfung)
        && nurPersonenMitGleicherWahlOderWahltermin.isAccept(verknuepfung);
  }

  protected abstract PersonenVergleichFunktion<E> getPersonenVergleichFunktion();
}
