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

import static java.util.stream.Collectors.toSet;

import java.util.Set;

import javax.ejb.Stateless;
import javax.enterprise.inject.Instance;
import javax.inject.Inject;

import de.ivu.elect.business.benutzerverwaltung.entity.Benutzer;
import de.ivu.elect.business.datei.entity.DateiExport;
import de.ivu.elect.business.datei.entity.DateiExportPK;
import de.ivu.elect.business.entschaedigung.control.AbstractPersonendatenEntschaedigungExportPostProcessor;
import de.ivu.elect.business.entschaedigung.control.AuszahlungExportContext;
import de.ivu.elect.business.entschaedigung.control.AuszahlungExportExchange;
import de.ivu.elect.business.entschaedigung.control.AuszahlungExportObject;
import de.ivu.elect.business.entschaedigung.control.AuszahlungProtokollierungDateiExport;
import de.ivu.elect.business.entschaedigung.entity.Auszahlung;
import de.ivu.elect.business.entschaedigung.entity.AuszahlungCalculated;
import de.ivu.elect.business.entschaedigung.entity.Entschaedigung;
import de.ivu.elect.business.exchange.control.AbstractExporter;
import de.ivu.elect.business.exchange.control.ExportExchange;
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.person.entity.Personendaten;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.business.wahl.entity.Wahltermin;

@Stateless
public class AuszahlungExporter extends AbstractExporter<AuszahlungExportObject, AuszahlungExportContext> {

  @Inject
  protected transient AuszahlungDAO auszahlungDAO;

  @Inject
  protected transient EntschaedigungDAO entschaedigungDAO;

  @Inject
  protected transient AuszahlungExportExchange auszahlungExportExchange;

  @Inject
  protected transient Instance<AbstractPersonendatenEntschaedigungExportPostProcessor> personendatenEntschaedigungExportPostProcessors;

  public AuszahlungExporter() {
    super();
  }

  @Override
  protected DateiExportArt getDateiExportArt() {
    return DateiExportArt.KONTODATEN_EXPORT;
  }

  @Override
  public ExportExchange<AuszahlungExportObject, AuszahlungExportContext> getExchange() {
    return auszahlungExportExchange;
  }

  @Override
  public AuszahlungExportObject getExportObject(AuszahlungExportContext context) {
    return new AuszahlungExportObject(new AuszahlungCalculated(attach(context.getAuszahlung()), entschaedigungDAO));
  }

  @Override
  protected void processContextAndDateiExportIfNecessary(AuszahlungExportContext context, DateiExport dateiExport) {
    Auszahlung auszahlung = attach(context.getAuszahlung());
    auszahlung.setDateiExport(dateiExport);

    auszahlungDAO.persist(auszahlung);
  }

  @Override
  public DateiExportPK export(FileFormat fileFormat, AuszahlungExportContext context, Mandant mandant, Wahl wahl, Wahltermin wahltermin) {
    DateiExportPK result = super.export(fileFormat, context, mandant, wahl, wahltermin);

    if (result != null) {
      AuszahlungExportObject exportObject = getExportObject(context);

      for (Entschaedigung entschaedigung : exportObject.getEntschaedigungen()) {
        for (AbstractPersonendatenEntschaedigungExportPostProcessor personendatenEntschaedigungExportPostProcessor : personendatenEntschaedigungExportPostProcessors) {
          personendatenEntschaedigungExportPostProcessor.onEntschaedigungExported(entschaedigung, context);
        }
      }
    }

    return result;
  }

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

    Auszahlung auszahlung = attach(exportObject.getAuszahlung());

    if (auszahlung != null) {
      Benutzer benutzer = context.getBenutzer();

      protokollierePersonendatenDateiExport(attachPersonendaten(auszahlung), dateiExport, benutzer);

      AuszahlungProtokollierungDateiExport.protokolliere(auszahlung, dateiExport, benutzer); // ELECTMUC-2909
    }
  }

  private Set< ? extends Personendaten> attachPersonendaten(Auszahlung auszahlung) {
    return auszahlung.getEntschaedigungen(entschaedigungDAO).stream() //
        .map(Entschaedigung::getPersonendaten) //
        .collect(toSet());
  }

  private Auszahlung attach(Auszahlung auszahlung) {
    return auszahlungDAO.attach(auszahlung);
  }
}
