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

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

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;

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

import de.ivu.elect.business.datei.entity.DateiExport;
import de.ivu.elect.business.datei.entity.FileType;
import de.ivu.elect.business.dokumente.boundary.AbstractDokumentGenerator;
import de.ivu.elect.business.dokumente.control.ProgressMonitor;
import de.ivu.elect.business.dokumente.entity.DokumentVorlage;
import de.ivu.elect.business.dokumente.entity.DokumentVorlageArt;
import de.ivu.elect.business.entschaedigung.control.AuszahlungDocumentContext;
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.person.boundary.PersonendatenDAO;
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 AuszahlungDocumentGenerator extends AbstractDokumentGenerator<Auszahlung, AuszahlungDocumentContext> {

  @Inject
  private transient AuszahlungDAO auszahlungDAO;

  @Inject
  private transient EntschaedigungDAO entschaedigungDAO;

  @Inject
  private transient PersonendatenDAO personendatenDAO;

  public AuszahlungDocumentGenerator() {
    super();
  }

  @Override
  public DokumentVorlageArt getDokumentVorlageArt() {
    return DokumentVorlageArt.AUSZAHLUNG;
  }

  @Override
  protected void postGeneriereDokument(DateiExport dateiExport, List<Auszahlung> auszahlungen, DokumentVorlage dokumentVorlage, FileType zieldateiTyp, Wahl wahl, Wahltermin wahltermin,
      AuszahlungDocumentContext context, ProgressMonitor monitor) {
    super.postGeneriereDokument(dateiExport, auszahlungen, dokumentVorlage, zieldateiTyp, wahl, wahltermin, context, monitor);

    protokollierePersonendatenDateiExport(attachPersonendaten(auszahlungen), dateiExport, dokumentVorlage, context.getBenutzer());
  }

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

  @Override
  protected Auszahlung attach(Auszahlung template, AuszahlungDocumentContext context) {
    Auszahlung auszahlung = attach(template);

    AuszahlungCalculated auszahlungCalculated = new AuszahlungCalculated(auszahlung, attach(auszahlung, context.getAuszahlungCalculated().getEntschaedigungen()));
    context.setAuszahlungCalculated(auszahlungCalculated);

    return auszahlungCalculated.getAuszahlung();
  }

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

  private List<Entschaedigung> attach(Auszahlung auszahlung, List<Entschaedigung> entschaedigungen) {
    List<Entschaedigung> result = new ArrayList<>();

    for (Entschaedigung entschaedigung : entschaedigungen) {
      if (entschaedigung.isPersistent()) {
        result.add(entschaedigungDAO.attach(entschaedigung));
      } else {
        Entschaedigung entschaedigungTransient = entschaedigung;
        entschaedigungTransient.setAuszahlung(auszahlung);
        entschaedigungTransient.setPersonendaten(attach(entschaedigungTransient.getPersonendaten()));

        result.add(entschaedigungTransient);
      }
    }

    return result;
  }

  private Personendaten attach(Personendaten personendaten) {
    return personendatenDAO.attach(personendaten);
  }
}
