package de.ivu.elect.business.gebietsbaum.control;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;

import javax.ejb.Singleton;
import javax.inject.Inject;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import de.ivu.elect.business.WahlOderWahlterminApp;
import de.ivu.elect.business.gebietsbaum.boundary.GebietDAO;
import de.ivu.elect.business.gebietsbaum.entity.AbstractGebiet;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.gebietsbaum.entity.GebietPruefkennzeichenGenerierenArt;
import de.ivu.elect.business.gebietsbaum.entity.GebietPruefkennzeichenGenerierenEindeutigkeit;
import de.ivu.elect.business.gebietsbaum.entity.PruefzifferAutomatischGenerierenFormat;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.business.wahl.entity.Wahltermin;

@Singleton
public class PruefkennzeichenAutomatischGenerierenSingleton implements Serializable {
  private static final long serialVersionUID = 1L;

  private static final Logger LOG = LoggerFactory.getLogger(PruefkennzeichenAutomatischGenerierenSingleton.class);

  @Inject
  private transient PruefkennzeichenGenerieren pruefkennzeichenGenerieren;

  @Inject
  private transient GebietDAO gebietDAO;

  @Inject
  private transient WahlOderWahlterminApp wahlOderWahlterminApp;

  public void generiere(Wahltermin wahltermin, PruefzifferAutomatischGenerierenFormat pruefzifferAutomatischGenerierenFormat) {
    LOG.info("Prüfziffergenerierung: " + wahltermin);

    if (pruefzifferAutomatischGenerierenFormat == null || pruefzifferAutomatischGenerierenFormat.isDeaktiviert()) {
      LOG.info("Keine Prüfziffergenerierung: " + wahltermin + ", keine Generierung: " + pruefzifferAutomatischGenerierenFormat);
    } else {
      Set<Gebiet> gebiete = bestimmeGebiete(wahltermin);

      if (gebiete.isEmpty() || gebiete.stream().noneMatch(g -> StringUtils.isBlank(g.getExterneId()))) {
        LOG.info("Prüfziffergenerierung: " + wahltermin + " keine Gebiete ohne Prüfkennzeichen");
        return;
      }

      pruefkennzeichenGenerieren
          .generierePruefkennzeichen(gebiete, GebietPruefkennzeichenGenerierenArt.from(pruefzifferAutomatischGenerierenFormat),
              GebietPruefkennzeichenGenerierenEindeutigkeit.WAHLUEBERGREIFEND_EINDEUTIG, false);

      LOG.info("Prüfziffergenerierung: " + pruefzifferAutomatischGenerierenFormat + ", " + wahltermin + " done");
    }
  }

  private Set<Gebiet> bestimmeGebiete(Wahltermin wahltermin) {
    HashSet<Gebiet> result = new HashSet<>();
    if (wahlOderWahlterminApp.isWahlterminApp()) {
      result.addAll(gebietDAO.findByWahltermin(wahltermin));
    } else {
      for (Wahl wahl : wahltermin.getWahlsByWahltermin()) {
        result.addAll(gebietDAO.findByWahl(wahl));
      }
    }

    return result.stream().filter(AbstractGebiet::isErfassungsgebiet).collect(Collectors.toSet());
  }
}
