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

import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

import de.ivu.elect.business.kandidatur.entity.Kandidatur;
import de.ivu.elect.business.person.entity.Personendaten;
import de.ivu.elect.business.person.entity.Wahlrechtsausschluss;
import de.ivu.elect.business.personenpruefung.control.wahlrecht.kriterium.AbstractWahlrechtGebietsartInReferenzGebietKriterium;
import de.ivu.elect.business.personenpruefung.control.wahlrecht.kriterium.HoechstalterAmStichtagKriterium;
import de.ivu.elect.business.personenpruefung.control.wahlrecht.kriterium.MindestalterAmStichtagKriterium;
import de.ivu.elect.business.personenpruefung.control.wahlrecht.kriterium.MindestaufenthaltAnAnschriftArtInGebietAmStichtagKriterium;
import de.ivu.elect.business.personenpruefung.control.wahlrecht.kriterium.PersonenregisterAbgleichbarkeitKriterium;
import de.ivu.elect.business.personenpruefung.control.wahlrecht.kriterium.PflichtangabeKriterium;
import de.ivu.elect.business.personenpruefung.control.wahlrecht.kriterium.StaatsangehoerigkeitKriterium;
import de.ivu.elect.business.personenpruefung.control.wahlrecht.kriterium.WahlrechtsausschlussKriterium;
import de.ivu.elect.business.personenpruefung.entity.HoechstalterAmWahlterminPersonPruefungKonfigurationCustomData;
import de.ivu.elect.business.personenpruefung.entity.MindestalterAmWahlterminPersonPruefungKonfigurationCustomData;
import de.ivu.elect.business.personenpruefung.entity.PersonPruefungKonfiguration;
import de.ivu.elect.business.personenpruefung.entity.PersonPruefungKonfigurationPersonentyp;
import de.ivu.elect.business.personenpruefung.entity.PersonPruefungKonfigurationTyp;
import de.ivu.elect.business.personenpruefung.entity.PflichtangabenPersonPruefungKonfigurationCustomData;
import de.ivu.elect.business.personenpruefung.entity.StaatsangehoerigkeitZugelassenPersonPruefungKonfigurationCustomData;
import de.ivu.elect.business.personenpruefung.entity.WahlrechtsausschlussPersonPruefungKonfigurationCustomData;

public class KandidaturWahlrechtMatcher extends AbstractPersonendatenWahlrechtMatcher {

  private static final long serialVersionUID = 1L;

  public KandidaturWahlrechtMatcher() {
    super();
  }

  private PersonPruefungKonfigurationPersonentyp getPersonPruefungKonfigurationPersonentyp() {
    return PersonPruefungKonfigurationPersonentyp.KANDIDAT;
  }

  @Override
  public List<PflichtangabeKriterium> collectPflichtangabeKriterien(Personendaten personendaten) {
    Optional<PersonPruefungKonfiguration> personPruefungKonfiguration = findPersonPruefungKonfiguration(PersonPruefungKonfigurationTyp.PFLICHTANGABEN, PersonPruefungKonfigurationPersonentyp.KANDIDAT,
        personendaten);

    if (personPruefungKonfiguration.isPresent()) {
      List<PflichtangabeKriterium> result = new ArrayList<>();

      for (WahlrechtPflichtangabe pflichtangabe : personPruefungKonfiguration.get().getCustomData(PflichtangabenPersonPruefungKonfigurationCustomData.class).getValues()) {
        result.add(new PflichtangabeKriterium(getDefaultPersonendatenClasses(), pflichtangabe));
      }

      return result;
    }

    return emptyList();
  }

  @Override
  public List<MindestalterAmStichtagKriterium> collectMindestalterAmStichtagKriterien(Personendaten personendaten) {
    Optional<PersonPruefungKonfiguration> personPruefungKonfiguration = findPersonPruefungKonfiguration(PersonPruefungKonfigurationTyp.MINDESTALTER_AM_WAHLTERMIN,
        getPersonPruefungKonfigurationPersonentyp(), personendaten);

    if (personPruefungKonfiguration.isPresent()) {
      Long mindestalterInJahren = personPruefungKonfiguration.get().getCustomData(MindestalterAmWahlterminPersonPruefungKonfigurationCustomData.class).getValue();

      if (mindestalterInJahren != null) {
        return asList(createMindestalterAmWahltagKriterium(personendaten, Math.toIntExact(mindestalterInJahren)));
      }
    }

    return emptyList();
  }

  @Override
  public List<HoechstalterAmStichtagKriterium> collectHoechstalterAmStichtagKriterien(Personendaten personendaten) {
    Optional<PersonPruefungKonfiguration> personPruefungKonfiguration = findPersonPruefungKonfiguration(PersonPruefungKonfigurationTyp.HOECHSTALTER_AM_WAHLTERMIN,
        getPersonPruefungKonfigurationPersonentyp(), personendaten);

    if (personPruefungKonfiguration.isPresent()) {
      Long hoechstalterInJahren = personPruefungKonfiguration.get().getCustomData(HoechstalterAmWahlterminPersonPruefungKonfigurationCustomData.class).getValue();

      if (hoechstalterInJahren != null) {
        return asList(createHoechstalterAmWahltagKriterium(personendaten, Math.toIntExact(hoechstalterInJahren)));
      }
    }

    return emptyList();
  }

  @Override
  public List<WahlrechtsausschlussKriterium> collectWahlrechtsausschlussKriterien(Personendaten personendaten) {
    Optional<PersonPruefungKonfiguration> personPruefungKonfiguration = findPersonPruefungKonfiguration(PersonPruefungKonfigurationTyp.WAHLRECHTSAUSSCHLUSS,
        PersonPruefungKonfigurationPersonentyp.KANDIDAT, personendaten);

    if (personPruefungKonfiguration.isPresent()) {
      List<WahlrechtsausschlussKriterium> result = new ArrayList<>();

      for (Wahlrechtsausschluss wahlrechtsausschluss : personPruefungKonfiguration.get().getCustomData(WahlrechtsausschlussPersonPruefungKonfigurationCustomData.class).getValues()) {
        result.add(new WahlrechtsausschlussKriterium(getDefaultPersonendatenClasses(), wahlrechtsausschluss));
      }

      return result;
    }

    return emptyList();
  }

  @Override
  public List<StaatsangehoerigkeitKriterium> collectStaatsangehoerigkeitKriterien(Personendaten personendaten) {
    Optional<PersonPruefungKonfiguration> personPruefungKonfiguration = findPersonPruefungKonfiguration(PersonPruefungKonfigurationTyp.STAATSANGEHOERIGKEIT,
        PersonPruefungKonfigurationPersonentyp.KANDIDAT, personendaten);

    if (personPruefungKonfiguration.isPresent()) {
      WahlrechtStaatsangehoerigkeit wahlrechtStaatsangehoerigkeit = personPruefungKonfiguration.get().getCustomData(StaatsangehoerigkeitZugelassenPersonPruefungKonfigurationCustomData.class)
          .getValue();

      return Collections.singletonList(new StaatsangehoerigkeitKriterium(getDefaultPersonendatenClasses(), wahlrechtStaatsangehoerigkeit));
    }

    return emptyList();
  }

  @Override
  public PersonenregisterAbgleichbarkeitKriterium collectPersonenregisterAbgleichbarkeitKriterium(Personendaten personendaten) {
    return new PersonenregisterAbgleichbarkeitKriterium(getDefaultPersonendatenClasses(), WahlrechtPersonenregisterAbgleichbarkeit.IRRELEVANT);
  }

  @Override
  public List<MindestaufenthaltAnAnschriftArtInGebietAmStichtagKriterium> collectMindestaufenthaltAnAnschriftArtInGebietAmStichtagKriterien(Personendaten personendaten) {
    return emptyList();
  }

  @Override
  public List< ? extends AbstractWahlrechtGebietsartInReferenzGebietKriterium> collectWahlrechtGebietsartInReferenzGebietKriterien(Personendaten personendaten) {
    return emptyList();
  }

  protected void requireKandidatur(Personendaten personendaten) {
    if (!personendaten.isInstanceOf(Kandidatur.class)) {
      throw new IllegalArgumentException("Personendaten muss Kandidatur sein [personendaten = " + personendaten + "]");
    }
  }
}
