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

import static java.util.Objects.nonNull;

import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.ejb.Stateless;
import javax.inject.Inject;

import de.ivu.elect.business.unterstuetzer.control.EintragungslisteByNummerComparator;
import de.ivu.elect.business.unterstuetzer.entity.Eintragungsliste;
import de.ivu.elect.business.unterstuetzer.entity.EintragungslisteEintragGueltigkeit;

@Stateless
public class EintragungslisteSearch extends AbstractEintragungslisteSearch {

  private static final Comparator<Eintragungsliste> DEFAULT_COMPARATOR = new EintragungslisteByNummerComparator();

  @Inject
  private transient EintragungslisteEintragExtendedDAO eintragungslisteEintragDao;

  @Inject
  private transient EintragungslisteExtendedDAO eintragungslisteExtendedDAO;

  public EintragungslisteSearch() {
    super();
  }

  @Override
  protected List<Eintragungsliste> querySearchResult(EintragungslisteSearchParameters searchParameters) {
    Map<Long, Eintragungsliste> eintragungslistePerId = new HashMap<>();

    streamCustomSearchResultRows(searchParameters).forEach(row -> {
      Long eintragungslisteId = (Long) row[0];

      EintragungslisteEintragGueltigkeit eintragungslisteEintragGueltigkeit = EintragungslisteEintragGueltigkeit.UNBEKANNT;

      if (nonNull(row[2])) {
        eintragungslisteEintragGueltigkeit = (EintragungslisteEintragGueltigkeit) row[2];
      }

      Eintragungsliste eintragungsliste = eintragungslistePerId.getOrDefault(eintragungslisteId,
          new Eintragungsliste());
      eintragungsliste.setId(eintragungslisteId);
      eintragungsliste.setNummer((Long) row[1]);
      eintragungsliste.updateTransientAnzahlEintragungslisteEintraegePerGueltigkeit(eintragungslisteEintragGueltigkeit,
          (Long) row[3]);

      eintragungslistePerId.put(eintragungslisteId, eintragungsliste);
    });

    eintragungslisteExtendedDAO.findByWahl(searchParameters.getSelectedWahl()).forEach(eintragungsliste -> {
      if (!eintragungslistePerId.containsKey(eintragungsliste.getId())) {
        for (EintragungslisteEintragGueltigkeit eintragungslisteEintragGueltigkeit : EintragungslisteEintragGueltigkeit
            .values()) {
          eintragungsliste
              .updateTransientAnzahlEintragungslisteEintraegePerGueltigkeit(eintragungslisteEintragGueltigkeit, 0L);
        }
        eintragungslistePerId.put(eintragungsliste.getId(), eintragungsliste);
      }
    });

    return eintragungslistePerId.values().stream().sorted(DEFAULT_COMPARATOR).collect(Collectors.toList());
  }

  private Stream<Object[]> streamCustomSearchResultRows(EintragungslisteSearchParameters searchParameters) {
    String nummer = "";

    if (nonNull(searchParameters.getNummer())) {
      nummer = String.valueOf(searchParameters.getNummer());
    }

    return eintragungslisteEintragDao.findByWahlAndWildcardNummerGroupedByEintragungslisteAndGueltigkeit(
        searchParameters.getSelectedWahl(), convertSearchPattern(nummer)).stream();
  }
}
