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

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.inject.Inject;

import org.apache.commons.lang3.StringUtils;

import de.ivu.elect.business.kandidatur.boundary.KandidaturExtendedDAO;
import de.ivu.elect.business.kandidatur.entity.Kandidatur;
import de.ivu.elect.business.wahlrechtspruefung.control.PruefkriteriumByPositionComparator;
import de.ivu.elect.business.wahlrechtspruefung.entity.Pruefkriterium;
import de.ivu.elect.business.wahlrechtspruefung.entity.PruefkriteriumKategorieInformation;
import de.ivu.elect.business.wahlrechtspruefung.entity.QWahlrechtspruefung;
import de.ivu.elect.business.wahlrechtspruefung.entity.Wahlrechtspruefung;
import de.ivu.elect.business.wahlvorschlag.boundary.WahlvorschlagExtendedDAO;
import de.ivu.elect.business.wahlvorschlag.entity.Wahlvorschlag;
import de.ivu.elect.jee.entity.QueryDsl;

public class WahlrechtspruefungSearch extends AbstractWahlrechtspruefungSearch {

  @Inject
  private transient WahlvorschlagExtendedDAO wahlvorschlagDAO;

  @Inject
  private transient KandidaturExtendedDAO kandidaturDAO;

  public WahlrechtspruefungSearch() {
    super();
  }

  @Override
  protected List<Wahlrechtspruefung> querySearchResult(WahlrechtspruefungSearchParameters searchParameters) {
    QueryDsl qdsl = dao.getQueryDsl();

    QWahlrechtspruefung wahlrechtspruefungTable = QWahlrechtspruefung.wahlrechtspruefung;
    filterWahlvorschlagUndKandidatur(searchParameters.getWahlvorschlag(), searchParameters.getKandidatur(), qdsl, wahlrechtspruefungTable);

    if (searchParameters.isNurSofortpruefungen()) {
      qdsl.eq(wahlrechtspruefungTable.pruefkriterium.teilDerSofortpruefung, Boolean.TRUE);
    }

    qdsl.eqIfNotNull(wahlrechtspruefungTable.wahlrechtspruefStatus, searchParameters.getWahlrechtspruefStatus());

    if (searchParameters.isWahlrechtlichRelevant()) {
      qdsl.eq(wahlrechtspruefungTable.pruefkriterium.wahlrechtlichRelevant, Boolean.TRUE);
    }

    qdsl.eqIfNotBlank(wahlrechtspruefungTable.pruefkriterium.kategorie, searchParameters.getKategorie());
    qdsl.eqIfNotBlank(wahlrechtspruefungTable.pruefkriterium.unterkategorie, searchParameters.getUnterkategorie());
    qdsl.orderBy(wahlrechtspruefungTable.pruefkriterium.position.asc());

    return qdsl.list(wahlrechtspruefungTable);
  }

  public PruefkriteriumKategorieInformation getKategorieInformationen(Wahlvorschlag wahlvorschlag, Kandidatur kandidatur) {
    PruefkriteriumKategorieInformation result = new PruefkriteriumKategorieInformation();

    List<Pruefkriterium> allePruefkriterienDesPruefObjektes = new ArrayList<>(ermittleAllePruefkriterienDesPruefObjektes(wahlvorschlag, kandidatur));
    Collections.sort(allePruefkriterienDesPruefObjektes, PruefkriteriumByPositionComparator.ASCENDING);

    for (Pruefkriterium pruefkriterium : allePruefkriterienDesPruefObjektes) {
      String kategorie = pruefkriterium.getKategorie();
      if (StringUtils.isNotBlank(kategorie) && result.getAlleKategorien().contains(kategorie)) {
        result.getAlleKategorien().add(kategorie);
      }
      String unterKategorie = pruefkriterium.getUnterkategorie();
      if (StringUtils.isNotBlank(unterKategorie) && result.getAlleUnterkategorien().contains(unterKategorie)) {
        result.getAlleUnterkategorien().add(unterKategorie);
      }
    }

    return result;
  }

  private Set<Pruefkriterium> ermittleAllePruefkriterienDesPruefObjektes(Wahlvorschlag wahlvorschlag, Kandidatur kandidatur) {
    QueryDsl qdsl = dao.getQueryDsl();

    QWahlrechtspruefung wahlrechtspruefungTable = QWahlrechtspruefung.wahlrechtspruefung;

    filterWahlvorschlagUndKandidatur(wahlvorschlag, kandidatur, qdsl, wahlrechtspruefungTable);

    List<Wahlrechtspruefung> pruefungen = qdsl.list(wahlrechtspruefungTable);

    Set<Pruefkriterium> result = new HashSet<>();

    for (Wahlrechtspruefung wahlrechtspruefung : pruefungen) {
      result.add(wahlrechtspruefung.getPruefkriterium());
    }

    return result;
  }

  private void filterWahlvorschlagUndKandidatur(Wahlvorschlag wahlvorschlag, Kandidatur kandidatur, QueryDsl qdsl, QWahlrechtspruefung wahlrechtspruefungTable) {
    qdsl.from(wahlrechtspruefungTable);
    qdsl.eq(wahlrechtspruefungTable.wahlvorschlag, wahlvorschlagDAO.attach(wahlvorschlag));

    if (kandidatur == null) {
      qdsl.isNull(wahlrechtspruefungTable.kandidatur);
    } else {
      qdsl.eq(wahlrechtspruefungTable.kandidatur, kandidaturDAO.attach(kandidatur));
    }
  }
}
