
package de.ivu.elect.was.exchange.ergebnis.eml;

import static java.util.Arrays.asList;

import java.io.OutputStream;
import java.util.Collection;
import java.util.EnumSet;
import java.util.Objects;
import java.util.Optional;

import javax.inject.Inject;

import de.ivu.elect.business.datei.entity.DateiFileNames;
import de.ivu.elect.business.datei.entity.FileType;
import de.ivu.elect.business.ergebnis.control.Eml510EmptyErgebnisExportExchange;
import de.ivu.elect.business.ergebnis.control.ErgebnisDatenCreator;
import de.ivu.elect.business.ergebnis.control.ErgebnisExportContext;
import de.ivu.elect.business.ergebnis.control.ErgebnisExportObject;
import de.ivu.elect.business.ergebnis.control.NlWasErgebnisArtefaktNachGebietErgebniseingabestatusExportContext;
import de.ivu.elect.business.ergebnis.entity.Stimmabgabeart;
import de.ivu.elect.business.exchange.control.FileFormat;
import de.ivu.elect.business.exchange.control.FileKonfiguration;
import de.ivu.elect.business.exchange.entity.DateiExportArt;
import de.ivu.elect.business.security.Customer;
import de.ivu.elect.business.stimmeingabe.entity.Ergebniseingabestatus;
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.business.wahl.entity.Wahl;
import de.ivu.elect.core.exchange.wahl.NlExportArtefaktNachSystemExportstatusRawExportMapper;
import de.ivu.elect.core.exchange.wahl.NlExportArtefaktNachSystemExportstatusFileNames;
import de.ivu.elect.exchange.ExportMapperProvidingDateiFileNames;
import de.ivu.elect.was.exchange.wahl.AbstractNlWasEmlNachGebietErgebniseingabestatusExportMapper;

public class Eml510EmptyErgebnisExportMapper extends AbstractNlWasEmlNachGebietErgebniseingabestatusExportMapper
    implements
      ExportMapperProvidingDateiFileNames<NlExportArtefaktNachSystemExportstatusExportObject, AbstractNlExportArtefaktNachSystemExportstatusExportContext> {

  private static final String FILE_FORMAT_NAME = "eml.510.empty.file.format";

  @Inject
  private transient ErgebnisDatenCreator ergebnisDatenCreator;

  @Inject
  private transient Eml510bPSBEmptyErgebnisExportMapper eml510bPSBEmptyErgebnisExportMapper;

  @Inject
  private transient Eml510cHSBEmptyErgebnisExportMapper eml510cHSBEmptyErgebnisExportMapper;

  @Inject
  private transient Eml510dCSBEmptyErgebnisExportMapper eml510dCSBEmptyErgebnisExportMapper;

  public Eml510EmptyErgebnisExportMapper() {
    super();
  }

  @Override
  public boolean supportsBulkExportNachSystemExportstatus() {
    return false; // ELECT-10319
  }

  @Override
  protected boolean isAcceptContextIgnoringSystemExportstatus(NlWasErgebnisArtefaktNachGebietErgebniseingabestatusExportContext context) {
    Optional<Abstract510EmptyErgebnisExportMapper> emlExportMapperIfPresent = getEml510EmptyErgebnisExportMapper(context);

    if (emlExportMapperIfPresent.isPresent()) {
      Abstract510EmptyErgebnisExportMapper emlExportMapper = emlExportMapperIfPresent.get();

      boolean result = Objects.equals(context.get(Eml510EmptyErgebnisExportExchange.CONTEXT_PARAM_FORMAT_NAME, String.class), emlExportMapper.getFileFormat().getName())
          && super.isAcceptContextIgnoringSystemExportstatus(context);

      return result && isEmlExportMapperAcceptContext(context, emlExportMapper);
    }

    return false;
  }

  public boolean isEmlExportMapperAcceptContext(NlWasErgebnisArtefaktNachGebietErgebniseingabestatusExportContext context, Abstract510EmptyErgebnisExportMapper emlExportMapper) {
    return emlExportMapper.isAcceptContext(createEmlExportContext(context));
  }

  @Override
  protected Collection<NlWahlart> collectWahlartenAccepted() {
    return NlWahlart.valuesListenwahl();
  }

  @Override
  protected boolean isAcceptWahlebene(Wahl wahl, Customer customer) {
    return collectEml510EmptyErgebnisExportMappersSortedByWahlebeneDesc().stream().anyMatch(exportMapper -> exportMapper.isWahlebenePassend(wahl));
  }

  @Override
  protected Collection<Ergebniseingabestatus> collectErgebniseingabestatusAccepted() {
    return EnumSet.allOf(Ergebniseingabestatus.class);
  }

  @Override
  public FileFormat getFileFormat() {
    return new FileFormat(FILE_FORMAT_NAME, Abstract510EmptyErgebnisExportMapper.FILE_FORMAT_TYPE);
  }

  @Override
  public boolean supportsTargetFilesSigning(AbstractNlExportArtefaktNachSystemExportstatusExportContext context) {
    return getEml510EmptyErgebnisExportMapper(context).map(emlExportMapper -> emlExportMapper.isSignEml(context.getWahl())).orElse(false);
  }

  @Override
  public String createTargetFileName(AbstractNlExportArtefaktNachSystemExportstatusExportContext context, FileType fileType) {
    return createTargetFileName(context, getMessage(getTargetFileFormat(context).getName()), fileType);
  }

  private FileFormat getTargetFileFormat(AbstractNlExportArtefaktNachSystemExportstatusExportContext context) {
    return getEml510EmptyErgebnisExportMapper(context).map(Abstract510EmptyErgebnisExportMapper::getFileFormat).orElse(getFileFormat());
  }

  @Override // ELECTVAPP-225
  public DateiFileNames getDateiExportFileNames(DateiExportArt dateiExportArt, AbstractNlExportArtefaktNachSystemExportstatusExportContext context) {
    return new NlExportArtefaktNachSystemExportstatusFileNames(context, getGebietDAO(), asList(getTargetFileFormat(context)));
  }

  @Override
  protected void serialize(NlExportArtefaktNachSystemExportstatusExportObject exportObject, OutputStream os, NlWasErgebnisArtefaktNachGebietErgebniseingabestatusExportContext context,
      FileKonfiguration fileKonfiguration, boolean closeOutputStream) throws Exception {
    Optional<Abstract510EmptyErgebnisExportMapper> emlExportMapperIfPresent = getEml510EmptyErgebnisExportMapper(context);

    if (emlExportMapperIfPresent.isPresent()) {
      ErgebnisExportContext emlExportContext = createEmlExportContext(context);

      new NlExportArtefaktNachSystemExportstatusRawExportMapper<>(context.getWahl(), emlExportMapperIfPresent.get()).serialize(os, context, createEmlExportObject(emlExportContext), emlExportContext,
          fileKonfiguration, closeOutputStream);
    }
  }

  private ErgebnisExportContext createEmlExportContext(AbstractNlExportArtefaktNachSystemExportstatusExportContext context) {
    return new ErgebnisExportContext(getErgebnisDAO().attach(((NlWasErgebnisArtefaktNachGebietErgebniseingabestatusExportContext) context).getErgebnis()));
  }

  private ErgebnisExportObject createEmlExportObject(ErgebnisExportContext context) {
    return new ErgebnisExportObject(ergebnisDatenCreator.createErgebnisDatenExporte(context.getErgebnis()), Stimmabgabeart.GESAMT);
  }

  protected Optional<Abstract510EmptyErgebnisExportMapper> getEml510EmptyErgebnisExportMapper(AbstractNlExportArtefaktNachSystemExportstatusExportContext context) {
    ErgebnisExportContext emlExportContext = createEmlExportContext(context);

    for (Abstract510EmptyErgebnisExportMapper emlExportMapper : collectEml510EmptyErgebnisExportMappersSortedByWahlebeneDesc()) {
      if (emlExportMapper.isAcceptContext(emlExportContext)) {
        return Optional.of(emlExportMapper);
      }
    }

    return Optional.empty();
  }

  private Collection<Abstract510EmptyErgebnisExportMapper> collectEml510EmptyErgebnisExportMappersSortedByWahlebeneDesc() {
    return asList(getEml510dEmptyErgebnisExportMapper(), getEml510cEmptyErgebnisExportMapper(), getEml510bEmptyErgebnisExportMapper());
  }

  protected Eml510bPSBEmptyErgebnisExportMapper getEml510bEmptyErgebnisExportMapper() {
    return eml510bPSBEmptyErgebnisExportMapper;
  }

  protected Eml510cHSBEmptyErgebnisExportMapper getEml510cEmptyErgebnisExportMapper() {
    return eml510cHSBEmptyErgebnisExportMapper;
  }

  protected Eml510dCSBEmptyErgebnisExportMapper getEml510dEmptyErgebnisExportMapper() {
    return eml510dCSBEmptyErgebnisExportMapper;
  }
}
