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

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

import javax.annotation.Nullable;
import javax.inject.Inject;

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.QPersonPruefungKonfiguration;
import de.ivu.elect.business.wahl.boundary.WahlExtendedDAO;
import de.ivu.elect.business.wahl.boundary.WahlterminExtendedDAO;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.business.wahl.entity.Wahltermin;
import de.ivu.elect.jee.entity.QueryDsl;

public class PersonPruefungKonfigurationSearch extends AbstractPersonPruefungKonfigurationSearch {

  @Inject
  private transient WahlterminExtendedDAO wahlterminExtendedDAO;

  @Inject
  private transient WahlExtendedDAO wahlExtendedDAO;

  @Override
  protected List<PersonPruefungKonfiguration> querySearchResult(PersonPruefungKonfigurationSearchParameters searchParameters) {

    Wahl wahl = searchParameters.getPersonPruefungKonfiguration().getWahl();
    Wahltermin wahltermin = searchParameters.getPersonPruefungKonfiguration().getWahltermin();
    if (wahl == null && wahltermin == null) {
      return Collections.emptyList();
    }
    QPersonPruefungKonfiguration personPruefungKonfiguration = QPersonPruefungKonfiguration.personPruefungKonfiguration;

    QueryDsl queryDsl = dao.getQueryDsl().from(personPruefungKonfiguration);

    if (wahl == null) {
      queryDsl.eq(personPruefungKonfiguration.wahltermin, wahlterminExtendedDAO.attach(wahltermin));
    } else {
      queryDsl.eq(personPruefungKonfiguration.wahl, wahlExtendedDAO.attach(wahl));
    }

    queryDsl.likeIfNotBlank(personPruefungKonfiguration.name, searchParameters.getPersonPruefungKonfiguration().getName());
    queryDsl.eqIfNotNull(personPruefungKonfiguration.typ, searchParameters.getPersonPruefungKonfiguration().getTyp());
    queryDsl.eqIfNotNull(personPruefungKonfiguration.personentyp, searchParameters.getPersonPruefungKonfiguration().getPersonentyp());
    queryDsl.eqIfNotNull(personPruefungKonfiguration.status, searchParameters.getPersonPruefungKonfiguration().getStatus());

    queryDsl.orderBy(personPruefungKonfiguration.typ.asc(), personPruefungKonfiguration.personentyp.asc(), personPruefungKonfiguration.name.asc());

    return queryDsl.list(personPruefungKonfiguration);

  }

  public List<PersonPruefungKonfigurationPersonentyp> findVorhandenePersonentypen(Wahltermin wahltermin, @Nullable Wahl wahl) {
    List<PersonPruefungKonfiguration> allePersonPruefungKonfigurationen;
    if (wahl == null) {
      allePersonPruefungKonfigurationen = dao.findByWahltermin(wahltermin);
    } else {
      allePersonPruefungKonfigurationen = dao.findByWahl(wahl);
    }
    return allePersonPruefungKonfigurationen.stream().map(PersonPruefungKonfiguration::getPersonentyp).distinct().collect(Collectors.toList());
  }

  public List<PersonPruefungKonfigurationTyp> findVorhandeneTypen(Wahltermin wahltermin, @Nullable Wahl wahl) {
    List<PersonPruefungKonfiguration> allePersonPruefungKonfigurationen;
    if (wahl == null) {
      allePersonPruefungKonfigurationen = dao.findByWahltermin(wahltermin);
    } else {
      allePersonPruefungKonfigurationen = dao.findByWahl(wahl);
    }
    return allePersonPruefungKonfigurationen.stream().map(PersonPruefungKonfiguration::getTyp).distinct().collect(Collectors.toList());
  }
}
