
package de.ivu.elect.dokumente.stimmeingabe;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Nonnull;
import javax.inject.Inject;

import de.ivu.elect.business.dokumente.entity.DokumentVorlage;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.gebietsbaum.entity.Wahldurchfuehrungsgebiet;
import de.ivu.elect.business.stimmeingabe.control.StimmeingabeDocumentByErgebniseingangExportContext;
import de.ivu.elect.business.stimmeingabe.control.WasStimmeingabeDocumentByErgebniseingangExportObject;
import de.ivu.elect.business.stimmeingabe.entity.Ergebniseingang;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.business.wahl.entity.Wahltermin;
import de.ivu.elect.util.NullComparator;
import de.ivu.elect.was.exchange.stimmeingabe.StimmeingabeDocumentByErgebniseingangExportMapper;

/**
 * Mapping mit Ergebniseingang.
 *
 * @see AbstractCoreStimmeingabeDocumentByErgebnisDatenExportMapper für Mapping mit ErgebnisDaten
 */
public abstract class AbstractWasStimmeingabeDocumentByErgebniseingangExportMapper
    extends
      AbstractCoreStimmeingabeDocumentExportMapper<StimmeingabeDocumentByErgebniseingangExportContext, WasStimmeingabeDocumentByErgebniseingangExportObject>
    implements
      StimmeingabeDocumentByErgebniseingangExportMapper {

  protected static final Comparator<Ergebniseingang> ERGEBNISEINGANG_COMPARATOR = (one, another) -> { // ELECT-9621
    if (one == null || another == null) {
      return NullComparator.NULL_BEFORE_NON_NULL_COMPARATOR.compare(one, another);
    }

    return GEBIET_COMPARATOR.compare(one.getWahldurchfuehrungsgebiet(), another.getWahldurchfuehrungsgebiet());
  };

  @Inject
  private transient WasStimmeingabeDocumentFactory stimmeingabeDocumentFactory;

  @Inject
  private transient StimmeingabeDocumentVorlaeufigEndgueltigFileNameConfig stimmeingabeDocumentFileNameConfig;

  protected AbstractWasStimmeingabeDocumentByErgebniseingangExportMapper() {
    super();
  }

  @Override
  public boolean isAcceptContext(StimmeingabeDocumentByErgebniseingangExportContext exportContext) {
    Wahl wahl = exportContext.getWahl();

    return exportContext.getErgebnisart() != null && wahl != null && isAcceptWahl(wahl);
  }

  protected boolean isAcceptWahl(@Nonnull Wahl wahl) {
    return true;
  }

  @Override
  protected DokumentVorlage getDokumentVorlage(StimmeingabeDocumentByErgebniseingangExportContext exportContext) {
    return exportContext.getDokumentVorlage();
  }

  @Override
  protected Gebiet findWahlgebiet(StimmeingabeDocumentByErgebniseingangExportContext exportContext, WasStimmeingabeDocumentByErgebniseingangExportObject exportObject) {
    return findWahlgebiet(exportObject.getErgebniseingaenge());
  }

  @Override
  protected Map<Gebiet, List<StimmeingabeDocument>> createDocumentsFuerErfassungsgebietPerUebergeordnetemGebiet(StimmeingabeDocumentContext context,
      StimmeingabeDocumentByErgebniseingangExportContext exportContext, WasStimmeingabeDocumentByErgebniseingangExportObject exportObject) {
    Map<Gebiet, List<StimmeingabeDocument>> result = new LinkedHashMap<>(); // ELECT-9621, Sortierung erhalten...

    List<Ergebniseingang> ergebniseingaengeSorted = new ArrayList<>(exportContext.collectEntitiesExportierbar(gebietDAO, exportObject.getErgebniseingaenge()));
    ergebniseingaengeSorted.sort(ERGEBNISEINGANG_COMPARATOR);

    for (Ergebniseingang ergebniseingang : ergebniseingaengeSorted) {
      Wahldurchfuehrungsgebiet erfassungsgebiet = ergebniseingang.getWahldurchfuehrungsgebiet();
      Gebiet uebergeordnetesGebiet = erfassungsgebiet.getUebergeordnetesGebiet();

      result.computeIfAbsent(uebergeordnetesGebiet, x -> new ArrayList<>()).add(getStimmeingabeDocumentFactory().createDocumentFuerErfassungsgebiet(context, ergebniseingang));
    }

    info("Erzeuge Dokumente mit Ergebniseingang");

    return result;
  }

  @Override
  protected AbstractWasStimmeingabeDocumentFactory getStimmeingabeDocumentFactory() {
    return stimmeingabeDocumentFactory;
  }

  @Override
  protected String getFileFormatName() {
    return stimmeingabeDocumentFileNameConfig.getFileFormatName();
  }

  @Override
  protected <K> String getDateiName(Wahl wahl, Wahltermin wahltermin, K dateiSchluessel) {
    return stimmeingabeDocumentFileNameConfig.getDateiName(dateiSchluessel, super.getDateiName(wahl, wahltermin, dateiSchluessel));
  }
}
