
package de.ivu.elect.exchange.zip;

import java.io.IOException;
import java.io.OutputStream;
import java.util.zip.ZipOutputStream;

import javax.inject.Inject;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.output.CloseShieldOutputStream;

import de.ivu.elect.business.datei.entity.FileType;
import de.ivu.elect.business.exchange.control.DefaultFileKonfiguration;
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.exchange.ExportMapper;

/**
 * HINT: Macht aus jedem (CSV-/XML-/...)ExportMapper einen ZipExportMapper.
 */
public class DelegateZipExportMapper {

  private static final String DEFAULT_ZIPENTRY_BASENAME = "export";

  @Inject
  private transient ZipOutputStreamBuilder zipOutputStreamBuilder;

  public DelegateZipExportMapper() {
    super();
  }

  public <T, C> FileFormat getFileFormat(ExportMapper<T, C> nonZipExportMapper) {
    FileFormat fileFormatArchived = nonZipExportMapper.getFileFormat();

    return new FileFormat(fileFormatArchived.getName(), FileType.ZIP, fileFormatArchived.getFileType(), nonZipExportMapper.getPriority());
  }

  public <T, C> void serialize(ExportMapper<T, C> nonZipExportMapper, T object, OutputStream os, C context, FileKonfiguration fileKonfiguration) throws MappingException {
    try (ZipOutputStream zos = zipOutputStreamBuilder.createZipOutputStream(os)) {

      zipOutputStreamBuilder.beginNewZipEntry(zos, createZipEntryName(nonZipExportMapper, fileKonfiguration));
      nonZipExportMapper.serialize(object, uncloseable(zos), context, createDelegateFileKonfiguration(nonZipExportMapper));

    } catch (IOException ex) {
      throw new MappingException("Exportdaten konnten nicht komprimiert werden [os=" + os + ", context=" + context + ", fileKonfiguration=" + fileKonfiguration + "]", ex);
    }
  }

  private String createZipEntryName(ExportMapper< ? , ? > nonZipExportMapper, FileKonfiguration fileKonfiguration) {
    String fileExtension = nonZipExportMapper.getFileFormat().getFileType().getFileExtension();

    return getFileBasename(fileKonfiguration) + "." + fileExtension;
  }

  private String getFileBasename(FileKonfiguration fileKonfiguration) {
    String fileBasename;

    if (fileKonfiguration instanceof DefaultFileKonfiguration) {
      fileBasename = FilenameUtils.getBaseName(fileKonfiguration.getFileName());
    } else {
      fileBasename = DEFAULT_ZIPENTRY_BASENAME;
    }

    return fileBasename;
  }

  protected FileKonfiguration createDelegateFileKonfiguration(ExportMapper< ? , ? > nonZipExportMapper) {
    return new DefaultFileKonfiguration(nonZipExportMapper.getFileFormat());
  }

  private static OutputStream uncloseable(OutputStream is) {
    return new CloseShieldOutputStream(is);
  }
}
