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

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

import de.ivu.elect.business.dokumente.control.ElectDokumentContext;
import de.ivu.elect.business.dokumente.entity.DokumentVorlage;
import de.ivu.elect.business.ergebnis.control.ErgebnisExchangeContext;
import de.ivu.elect.business.ergebnis.entity.Ergebnis;
import de.ivu.elect.business.gebietsbaum.boundary.AbstractGebietDAO;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;

public class StimmeingabeDocumentByErgebnisDatenExportContext extends AbstractStimmeingabeDocumentExportContext {

  private static final long serialVersionUID = 1L;

  private final Ergebnis ergebnis;

  private final Gebiet wurzelgebiet;

  private Collection<Gebiet> stimmzettelgebiete;

  private Collection<Gebiet> erfassungsgebiete;

  public StimmeingabeDocumentByErgebnisDatenExportContext(ElectDokumentContext context, ErgebnisExchangeContext ergebnisExchangeContext, Ergebnis ergebnis, Gebiet wurzelgebiet,
                                                          DokumentVorlage dokumentVorlage, boolean documentFuerWahlgebietRequired, boolean sectionErfassteStimmzettelExcluded, boolean sectionZaehllisteElektronischExcluded, boolean eingabenExcluded) {
    super(context, ergebnisExchangeContext, dokumentVorlage, documentFuerWahlgebietRequired, sectionErfassteStimmzettelExcluded,
        sectionZaehllisteElektronischExcluded, eingabenExcluded);

    this.ergebnis = ergebnis;

    this.wurzelgebiet = wurzelgebiet;
  }

  public Ergebnis getErgebnis() {
    return ergebnis;
  }

  /**
   * Wahlkreise, Stimmkreise, die Gemeinde selbst o.ä.
   */
  @Deprecated // nicht verwenden für neue Sachen
  public Collection<Gebiet> getStimmzettelgebiete() {
    if (stimmzettelgebiete == null) {
      stimmzettelgebiete = findStimmzettelgebiete();
    }

    return stimmzettelgebiete;
  }

  private Collection<Gebiet> findStimmzettelgebiete() {
    // ELECT-3139 - Vorlagen für Schnellmeldungen und Niederschriften nur einmal pro Wahlkreis generieren
    Set<Gebiet> result = new HashSet<>();

    if (ergebnis != null) {
      if (wurzelgebiet == null) {
        return Collections.emptyList();
      }

      for (Gebiet gebiet : wurzelgebiet.getGebietUndAlleUntergeordnetenGebieteAllerEbenen()) {
        if (gebiet.isUnterstesGebiet() && gebiet.isErgebnisRelevant()) {
          Gebiet obergebiet = gebiet.getUebergeordnetesDirektwahlgebiet();

          if (obergebiet == null) {
            obergebiet = gebiet.getUebergeordnetesListenwahlgebiet();
          }

          if (obergebiet != null) {
            result.add(obergebiet);
          }
        }
      }

      // Für Volksentscheide?
      if (result.isEmpty()) {
        result.add(wurzelgebiet);
      }
    }

    return result;
  }

  public Collection<Gebiet> getErfassungsgebiete(AbstractGebietDAO gebietDAO) {
    return collectEntitiesExportierbar(gebietDAO, getErfassungsgebiete());
  }

  /**
   * Die Wahlbezirke/Stimmbezirke, falls bereits vorhanden.
   */
  @Deprecated // nicht verwenden für neue Sachen
  private Collection<Gebiet> getErfassungsgebiete() {
    if (erfassungsgebiete == null) {
      erfassungsgebiete = filterErfassungsgebiete(getStimmzettelgebiete());
    }

    return erfassungsgebiete;
  }

  private Collection<Gebiet> filterErfassungsgebiete(Collection<Gebiet> obergebiete) {
    Collection<Gebiet> result = new ArrayList<>();

    for (Gebiet obergebiet : obergebiete) {
      Collection<Gebiet> untergebiete = obergebiet.getNurGebieteAufUntersterEbene();

      if (untergebiete.isEmpty()) {
        // ELECT-6371.
        if (obergebiet.isErfassungsgebiet()) {
          result.add(obergebiet);
        }
      } else {
        for (Gebiet untergebiet : untergebiete) {
          if (untergebiet.isErfassungsgebiet()) {
            result.add(untergebiet);
          }
        }
      }
    }

    return result;
  }

  public Gebiet getWurzelgebiet() {
    return wurzelgebiet;
  }
}
