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

import static java.util.Collections.emptyList;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.inject.Inject;

import de.ivu.elect.business.ergebnis.control.SitzeByGruppeImGebietRelativePositionAbgeleitetComparator;
import de.ivu.elect.business.ergebnis.entity.Ergebnis;
import de.ivu.elect.business.ergebnis.entity.Sitze;
import de.ivu.elect.business.gebietsbaum.boundary.GebietExtendedDAO;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.gruppe.entity.Gruppe;
import de.ivu.elect.business.gruppeimgebiet.boundary.GruppeImGebietExtendedDAO;
import de.ivu.elect.business.gruppeimgebiet.entity.GruppeImGebietTK;

/**
 * Nicht als Vorlage verwenden, es werden spezielle "Sitze" zurückgeliefert
 */
public class SitzeSearch extends AbstractSitzeSearch {

  @Inject
  private transient GebietExtendedDAO gebietExtendedDAO;

  @Inject
  private transient GruppeImGebietExtendedDAO gruppeImGebietExtendedDAO;

  @Inject
  private transient SitzeZusammenfasser sitzeZusammenfasser;

  public SitzeSearch() {
    super();
  }

  @Override
  protected List<Sitze> querySearchResult(SitzeSearchParameters searchParameters) {
    Ergebnis ergebnis = searchParameters.getErgebnis();

    Gebiet gebietSelected = gebietExtendedDAO.attach(searchParameters.getGebiet());

    if (ergebnis == null || gebietSelected == null) {
      return emptyList();
    }

    Map<Gruppe, Set<Sitze>> sitzePerGruppe = new HashMap<>();

    for (Sitze sitze : dao.findByErgebnis(ergebnis)) {
      Gebiet gebiet = sitze.getGebiet();

      if (gebiet.equals(gebietSelected) || gebiet.isUntergebietVon(gebietSelected)) {
        sitzePerGruppe.computeIfAbsent(sitze.getGruppe(), x -> new HashSet<>()).add(sitze);
      }
    }

    if (sitzePerGruppe.isEmpty()) {
      return emptyList();
    }

    List<Sitze> result = new ArrayList<>();

    Long id = -1L;

    for (Entry<Gruppe, Set<Sitze>> entry : sitzePerGruppe.entrySet()) {
      result.add(sitzeZusammenfasser.fasseSitzeZusammen(id--, entry.getKey(), gebietSelected, entry.getValue()));
    }

    if (!result.isEmpty()) {
      result.sort(new SitzeByGruppeImGebietRelativePositionAbgeleitetComparator(GruppeImGebietTK.mappeGruppeImGebietNachTK(gruppeImGebietExtendedDAO.findByGebiet(gebietSelected))));
    }

    return result;
  }
}
