
package de.ivu.elect.was.exchange.okwahl;

import java.io.OutputStream;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import java.util.SortedMap;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.inject.Inject;

import de.ivu.elect.business.datei.entity.FileType;
import de.ivu.elect.business.ergebnis.boundary.ErgebnisdokumentTypPerWahlartResolver;
import de.ivu.elect.business.exchange.control.FileFormat;
import de.ivu.elect.business.exchange.control.FileKonfiguration;
import de.ivu.elect.business.exchange.control.MappingException;
import de.ivu.elect.business.gebietsbaum.boundary.WahlverwaltungGebietDescriptor;
import de.ivu.elect.business.gebietsbaum.boundary.WahlverwaltungGebietInformation;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.core.exchange.gebietsbaum.WahlverwaltungGebietInformationCollector;
import de.ivu.elect.jee.faces.Messages;

public abstract class AbstractOkWahlZipExportMapper<T, C> {

  @Inject
  protected transient Messages messages;

  @Inject
  protected transient WahlverwaltungGebietInformationCollector wahlverwaltungGebietInformationCollector;

  @Inject
  protected transient ErgebnisdokumentTypPerWahlartResolver ergebnisdokumentTypPerWahlartResolver;

  protected AbstractOkWahlZipExportMapper() {
    super();
  }

  public abstract boolean isAcceptContext(C context);

  public FileFormat getFileFormat() {
    return new FileFormat(getFileFormatName(), getFileType(), getFileTypeArchived());
  }

  public abstract String getFileFormatName();

  public FileType getFileType() {
    return FileType.ZIP;
  }

  private FileType getFileTypeArchived() {
    return getSimpleExportMapper().getFileType();
  }

  public void serialize(T exportObject, OutputStream os, C context, Wahl wahl, FileKonfiguration fileKonfiguration) throws MappingException {
    try {
      ZipOutputStream zos = new ZipOutputStream(os);

      FileType zipEntryFileType = getFileTypeArchived();
      int zipEntryCount = 0;

      for (Entry<WahlverwaltungGebietInformation, SortedMap<WahlverwaltungGebietInformation, List<WahlverwaltungGebietDescriptor>>> entryPerStimmzettelgebiet : collectErfassungsgebieteGroupedByDefault(
          wahl)) {
        zipEntryCount++;

        WahlverwaltungGebietInformation stimmzettelgebietInformation = entryPerStimmzettelgebiet.getKey();

        // NOTE, dass bspw. bei der EUW ggf. weder Stimm- noch Wahlkreisnummer hinterlegt ist und deshalb ein generischer Dateiname erzeugt wird!
        String zipEntryFileName = getZipEntryFileNamePrefix(wahl, messages) + stimmzettelgebietInformation.createFileNameOrDefaultByIndex(fileKonfiguration, zipEntryFileType, zipEntryCount);
        zos.putNextEntry(new ZipEntry(zipEntryFileName));

        getSimpleExportMapper().serialize(exportObject, zos, context, entryPerStimmzettelgebiet, false);

        zos.closeEntry();
      }

      zos.finish();
    } catch (Exception ex) {
      throw new MappingException(ex.getMessage(), ex);
    }
  }

  protected String getZipEntryFileNamePrefix(Wahl wahl, Messages messages) {
    return "";
  }

  private Set<Entry<WahlverwaltungGebietInformation, SortedMap<WahlverwaltungGebietInformation, List<WahlverwaltungGebietDescriptor>>>> collectErfassungsgebieteGroupedByDefault(Wahl wahl) {
    // NOTE ELECTMUC-2353, dass im Gegensatz zu den V1-V7-Dokumenten dieses Exportformat scheinbar KEINE (interpolierte) GEMEINDENUMMER PER ORTS-/STADTBEZIRK, also bspw. MUC,
    // erfordert, cf. ErgebnisExportGebietFormatter#formatGebietsreferenzRegionalangaben!
    boolean gemeindeVerwaltungseinheitseinteilungIgnored = true;

    boolean erfassungsgebietErfasstInAnderemGebietIgnored = true; // ELECT-12557, bisheriges Verhalten...

    return wahlverwaltungGebietInformationCollector.collectErfassungsgebieteGroupedByDefault(wahl, gemeindeVerwaltungseinheitseinteilungIgnored, erfassungsgebietErfasstInAnderemGebietIgnored,
        (stimmzettelgebietInformation, gemeindeInformation, erfassungsgebietDescriptor) -> erfassungsgebietDescriptor).entrySet();
  }

  protected abstract AbstractOkWahlCsvExportMapper<T, C, ? > getSimpleExportMapper();
}
