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

import static java.util.Arrays.asList;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashSet;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.inject.Inject;

import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import de.ivu.elect.business.CurrentCustomer;
import de.ivu.elect.business.datei.boundary.DateiImportDAO;
import de.ivu.elect.business.datei.entity.DateiFileNames;
import de.ivu.elect.business.datei.entity.DateiImport;
import de.ivu.elect.business.datei.entity.FileType;
import de.ivu.elect.business.exchange.control.FileFormat;
import de.ivu.elect.business.exchange.control.FileKonfiguration;
import de.ivu.elect.business.exchange.control.ImportExportStreamCreator;
import de.ivu.elect.business.exchange.control.MappingException;
import de.ivu.elect.business.exchange.entity.DateiExportArt;
import de.ivu.elect.business.exchange.entity.DateiImportArt;
import de.ivu.elect.business.exchange.entity.ImportStatus;
import de.ivu.elect.business.gebietsbaum.boundary.GebietDAO;
import de.ivu.elect.business.system.boundary.SystemLogWriter;
import de.ivu.elect.business.system.entity.SystemLogQuelle;
import de.ivu.elect.business.wahl.control.AbstractNlExportArtefaktNachSystemExportstatusExportContext;
import de.ivu.elect.business.wahl.control.NlExportArtefaktNachSystemExportstatusExportObject;
import de.ivu.elect.business.wahl.entity.NlWahlart;
import de.ivu.elect.core.exchange.wahl.NlExportArtefaktNachSystemExportstatusFileNames;
import de.ivu.elect.exchange.ExportMapperProvidingDateiFileNames;
import de.ivu.elect.jee.faces.Messages;

public class NlStimmeingabenImportiertZipExportMapper
    implements
      ExportMapperProvidingDateiFileNames<NlExportArtefaktNachSystemExportstatusExportObject, AbstractNlExportArtefaktNachSystemExportstatusExportContext> {

  public static final FileFormat FILE_FORMAT = new FileFormat("eml.510b.importiert.file.format", FileType.ZIP);

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

  @Inject
  private transient GebietDAO gebietDAO;

  @Inject
  private transient Messages messages;

  @Inject
  private transient CurrentCustomer currentCustomer;

  @Inject
  private transient DateiImportDAO dateiImportDAO;

  @Inject
  private transient ImportExportStreamCreator streamCreator;

  @Inject
  private transient SystemLogWriter systemLogWriter;

  public NlStimmeingabenImportiertZipExportMapper() {
    super();
  }

  @Override
  public void serialize(NlExportArtefaktNachSystemExportstatusExportObject object, OutputStream os, AbstractNlExportArtefaktNachSystemExportstatusExportContext context,
      FileKonfiguration fileKonfiguration) throws MappingException {
    try (ZipOutputStream zos = new ZipOutputStream(os)) {
      Set<String> dateinamen = new HashSet<>();
      for (DateiImport dateiImport : dateiImportDAO.findByDateiImportArtAndWahlOrderBeiErstellungszeitpunktDesc(DateiImportArt.STIMMEINGABE_IMPORT, context.getWahl())) {
        if (ImportStatus.IMPORTIERT.equals(dateiImport.getImportStatus())) {
          String gespeicherterDateiname = dateiImport.getDateiname();
          String originalDateiname = dateiImport.getDatei().getOriginalDateiname();
          try (InputStream dateiImportInputStream = dateiImport.getDatei().createInputStream(streamCreator)) {
            String dateiname = originalDateiname;
            int anzahlGleicherDateinamen = 1;
            while (dateinamen.contains(dateiname)) {
              dateiname = erweitereDateiname(originalDateiname, ++anzahlGleicherDateinamen);
            }
            dateinamen.add(dateiname);
            ZipEntry zipEntry = new ZipEntry(dateiname);
            zos.putNextEntry(zipEntry);
            IOUtils.copy(dateiImportInputStream, zos);
            zos.closeEntry();
          } catch (IOException e) {
            String errorMsg = messages.getMessageForMessageKey("eml.510b.importiert.export.error.datei", gespeicherterDateiname, originalDateiname);
            systemLogWriter.writeWarnLogMessageFuerMandant(context.getMandant(), errorMsg, e, SystemLogQuelle.EXPORTER);
            LOG.warn(errorMsg, e);
          }
        }
      }
    } catch (IOException e) {
      String errorMsg = messages.getMessageForMessageKey("eml.510b.importiert.export.error");
      systemLogWriter.writeErrorLogMessageFuerMandant(context.getMandant(), errorMsg, e, SystemLogQuelle.EXPORTER);
      LOG.error(errorMsg, e);
    }
  }

  private String erweitereDateiname(String originalDateiname, int nrDerKopie) {
    int indexDateiendung = originalDateiname.lastIndexOf('.');
    StringBuilder sb = new StringBuilder(originalDateiname.substring(0, indexDateiendung));
    sb.append("(");
    sb.append(nrDerKopie);
    sb.append(")");
    sb.append(originalDateiname.substring(indexDateiendung));
    return sb.toString();
  }

  @Override
  public DateiFileNames getDateiExportFileNames(DateiExportArt dateiExportArt, AbstractNlExportArtefaktNachSystemExportstatusExportContext context) {
    return new NlExportArtefaktNachSystemExportstatusFileNames(context, gebietDAO, asList(getFileFormat()));
  }

  @Override
  public FileFormat getFileFormat() {
    return FILE_FORMAT;
  }

  @Override
  public boolean isAcceptContext(AbstractNlExportArtefaktNachSystemExportstatusExportContext context) {
    return NlWahlart.isWasHSB(context.getWahl(), currentCustomer.getCustomer());
  }
}
