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

import static java.util.Objects.requireNonNull;

import java.io.Serializable;
import java.util.Collection;
import java.util.Date;

import javax.annotation.Nonnull;

import de.ivu.elect.business.person.entity.Personendaten;
import de.ivu.elect.business.wahl.boundary.WahlartTemplate;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.business.wahl.entity.Wahltermin;
import de.ivu.elect.business.wahl.entity.WahlterminStichtagCalculator;

public abstract class AbstractPersonendatenMatcher implements Serializable {

  private static final long serialVersionUID = 1L;

  protected AbstractPersonendatenMatcher() {
    super();
  }

  public boolean matches(Personendaten personendaten) {
    requireNonNull(personendaten, "Personendaten darf nicht null sein");

    return matchesInternal(personendaten);
  }

  protected abstract boolean matchesInternal(@Nonnull Personendaten personendaten);

  protected Date getWahltag(Personendaten personendaten) {
    Wahltermin wahltermin = personendaten.getWahltermin();

    requireNonNull(wahltermin, "Wahltermin darf nicht null sein");

    return wahltermin.getWahldatum();
  }

  protected Date calculateStichtagVormWahltagByAnzahlTage(Personendaten personendaten, int anzahlTage) {
    return WahlterminStichtagCalculator.calculateTagVormWahltagByAnzahlTage(personendaten.getWahltermin(), anzahlTage);
  }

  protected boolean containsWahlart(Collection<WahlartTemplate> wahlarten, Wahl wahl) {
    for (WahlartTemplate wahlart : wahlarten) {
      if (wahlart.equalsWahlart(wahl)) {
        return true;
      }
    }

    return false;
  }

  protected boolean notEmptyAndAllMatch(Collection< ? extends PersonendatenMatcherKriterium> kriterien, Personendaten personendaten) {
    return kriterien.isEmpty() || !kriterien.stream().anyMatch(kriterium -> kriterium.matchesNot(personendaten));
  }

  protected boolean notEmptyAndAnyMatch(Collection< ? extends PersonendatenMatcherKriterium> kriterien, Personendaten personendaten) {
    return kriterien.isEmpty() || kriterien.stream().anyMatch(kriterium -> kriterium.matches(personendaten));
  }

  protected boolean isAuswaertig(Personendaten personendaten) {
    return Boolean.TRUE.equals(personendaten.getAuswaertig());
  }
}
