
package de.ivu.elect.business.wahl.boundary;

import java.io.IOException;
import java.io.OutputStream;
import java.util.Collection;
import java.util.HashSet;

import javax.inject.Inject;

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

import de.ivu.elect.business.customdata.entity.CustomDataStorage;
import de.ivu.elect.business.datei.entity.DateiExport;
import de.ivu.elect.business.datei.entity.DateiFileNames;
import de.ivu.elect.business.exchange.control.AbstractExporter;
import de.ivu.elect.business.exchange.control.FileFormat;
import de.ivu.elect.business.exchange.entity.DateiExportArt;
import de.ivu.elect.business.mandant.entity.Mandant;
import de.ivu.elect.business.wahl.control.AbstractNlExportArtefaktNachSystemExportstatusExportContext;
import de.ivu.elect.business.wahl.control.NlExportArtefaktNachSystemExportstatusBulkExporterHelper;
import de.ivu.elect.business.wahl.control.NlExportArtefaktNachSystemExportstatusExportObject;
import de.ivu.elect.business.wahl.control.NlHashByteArrayOutputStream;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.business.wahl.entity.Wahltermin;

public abstract class AbstractNlExportArtefaktNachSystemExportstatusBulkExporter
    extends
      AbstractExporter<NlExportArtefaktNachSystemExportstatusExportObject, AbstractNlExportArtefaktNachSystemExportstatusExportContext> {

  public static final DateiExportArt DATEI_EXPORT_ART = DateiExportArt.GEBIET_EXPORT;

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

  @Inject
  private transient WahlDAO wahlDAO;

  @Inject
  private transient NlExportArtefaktNachSystemExportstatusBulkExporterHelper nlExportArtefaktNachSystemExportstatusBulkExporterHelper;

  protected AbstractNlExportArtefaktNachSystemExportstatusBulkExporter() {
    super();
  }

  @Override
  protected DateiExportArt getDateiExportArt() {
    return DATEI_EXPORT_ART;
  }

  @Override
  public DateiFileNames getDateiExportFileNames(FileFormat fileFormat, AbstractNlExportArtefaktNachSystemExportstatusExportContext context) {
    return super.getDateiExportFileNames(fileFormat, context);
  }

  @Override
  public NlExportArtefaktNachSystemExportstatusExportObject getExportObject(AbstractNlExportArtefaktNachSystemExportstatusExportContext context) {
    return new NlExportArtefaktNachSystemExportstatusExportObject(wahlDAO.attach(context.getWahl()));
  }

  @Override
  protected void processContextAndDateiExportIfNecessary(AbstractNlExportArtefaktNachSystemExportstatusExportContext context, DateiExport dateiExport) {
    super.processContextAndDateiExportIfNecessary(context, dateiExport);

    nlExportArtefaktNachSystemExportstatusBulkExporterHelper.aktualisiereWahldaten(context); // ELECT-10910

    // ELECT-11916, Wahl- und deren CustomData-Änderungen aus vorheriger Transaktion "sichtbar" machen...
    Wahl wahl = wahlDAO.refresh(context.getWahl());

    CustomDataStorage customDataStorage = wahl.getCustomDataStorage();

    if (customDataStorage != null) {
      wahlDAO.getEntityManager().refresh(customDataStorage);
      customDataStorage.clearCustomDataCache();
    }
  }

  @Override
  protected void postExport(NlExportArtefaktNachSystemExportstatusExportObject exportObject, DateiExport dateiExport, FileFormat fileFormat,
      AbstractNlExportArtefaktNachSystemExportstatusExportContext context, Mandant mandant, Wahl wahl, Wahltermin wahltermin) {
    super.postExport(exportObject, dateiExport, fileFormat, context, mandant, wahl, wahltermin);

    Collection<NlExportArtefaktNachSystemExportstatus> artefakteInDateiExport = new HashSet<>(context.getArtefakteInDateiExport());

    // ELECTVAPP-794, ELECTVAPP-795
    for (NlExportArtefaktNachSystemExportstatus artefakt : artefakteInDateiExport) {
      if (!artefakt.isPersistent()) {
        FileFormat artefaktFileFormat = artefakt.getFileFormat();

        info("Erzeuge EXTRA-DateiExport [" //
            + "wahl = " + context.getWahl().getName() + ", " //
            + "fileFormat = " + artefaktFileFormat.getName() + ", " //
            + "fileType = " + artefaktFileFormat.getFileType() //
            + "]");

        DateiExport artefaktDateiExport = createDateiExport(artefaktFileFormat, artefakt.getDateiFileNames(getMessages(), getDateiExportArt()), context, mandant, wahl, wahltermin);

        try (OutputStream os = createOutputStreamAndDateiExport(artefaktFileFormat, context, artefaktDateiExport)) {
          FileUtils.copyFile(artefakt.getFile(), os);

          context.addArtefaktInDateiExport(new NlExportArtefaktNachSystemExportstatus(artefaktFileFormat, artefaktDateiExport));
        } catch (IOException ex) {
          handleExportException(ex, wahltermin, wahl);

          throw new RuntimeException(ex.getMessage(), ex);
        }
      }
    }

    context.addArtefaktInDateiExport(new NlExportArtefaktNachSystemExportstatus(fileFormat, dateiExport));
  }

  @Override
  protected OutputStream createOutputStreamAndDateiExport(FileFormat fileFormat, AbstractNlExportArtefaktNachSystemExportstatusExportContext context, DateiExport dateiExport) {
    return new NlHashByteArrayOutputStream(super.createOutputStreamAndDateiExport(fileFormat, context, dateiExport), dateiExport.getDatei());
  }

  protected void info(String format, Object... params) {
    LOG.info(format, params);
  }
}
