
package de.ivu.elect.presentation.dokumente;

import static java.util.Arrays.asList;
import static java.util.stream.Collectors.toList;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.Future;
import java.util.function.Predicate;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.enterprise.event.Observes;
import javax.enterprise.event.Reception;
import javax.inject.Inject;

import org.apache.deltaspike.core.api.scope.GroupedConversation;
import org.primefaces.event.FileUploadEvent;
import org.primefaces.model.DefaultStreamedContent;
import org.primefaces.model.StreamedContent;
import org.primefaces.model.file.UploadedFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import de.ivu.elect.business.datei.boundary.DateiExportConversationSelect;
import de.ivu.elect.business.datei.boundary.DateiExportEdit;
import de.ivu.elect.business.datei.boundary.DateiExportExtendedDAO;
import de.ivu.elect.business.datei.boundary.DateiExportSearchParameters;
import de.ivu.elect.business.datei.entity.DateiConstants;
import de.ivu.elect.business.datei.entity.DateiExport;
import de.ivu.elect.business.datei.entity.DateiExportPK;
import de.ivu.elect.business.datei.entity.FileType;
import de.ivu.elect.business.datei.entity.FileTypeResolver;
import de.ivu.elect.business.dokumente.boundary.AbstractDokumentGenerator;
import de.ivu.elect.business.dokumente.boundary.DokumentVorlageExtendedDAO;
import de.ivu.elect.business.dokumente.control.DokumentGenerierenSupportedOpenOfficeFileFormats;
import de.ivu.elect.business.dokumente.control.ElectDokumentContext;
import de.ivu.elect.business.dokumente.entity.DokumentGenerierenProgress;
import de.ivu.elect.business.dokumente.entity.DokumentVorlage;
import de.ivu.elect.business.dokumente.entity.DokumentVorlageArt;
import de.ivu.elect.business.exchange.control.FileFormat;
import de.ivu.elect.business.exchange.control.ImportExportStreamCreator;
import de.ivu.elect.business.exchange.entity.DateiExportArt;
import de.ivu.elect.business.gebietsbaum.boundary.GebietSelectChangeEvent;
import de.ivu.elect.business.gebietsbaum.boundary.GebietSessionSelect;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.mandant.entity.Mandant;
import de.ivu.elect.business.security.UseCasePermission;
import de.ivu.elect.business.security.control.ElectCommonPrincipal;
import de.ivu.elect.business.wahl.boundary.WahlSelectChangeEvent;
import de.ivu.elect.business.wahl.boundary.WahlSessionSelector;
import de.ivu.elect.business.wahl.boundary.WahlterminSelectChangeEvent;
import de.ivu.elect.business.wahl.boundary.WahlterminSessionSelect;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.business.wahl.entity.Wahltermin;
import de.ivu.elect.jee.faces.FacesContextUtil;
import de.ivu.elect.jee.faces.FacesMessageUtil;
import de.ivu.elect.jee.faces.PreConditionCheck;
import de.ivu.elect.jee.faces.upload.UploadedFileWithCanonicalFilename;
import de.ivu.elect.jee.presentation.dynamicform.AdvancedDynaFormModel;
import de.ivu.elect.jee.presentation.dynamicform.FormBuilder;
import de.ivu.elect.jee.presentation.redirect.Redirect;
import de.ivu.elect.jee.presentation.security.StartViewResolver;
import de.ivu.elect.jee.presentation.view.AbstractView;
import de.ivu.elect.presentation.View;
import de.ivu.elect.presentation.ViewHavingFileUpload;
import de.ivu.elect.presentation.datei.DateiExportSearchView;
import de.ivu.elect.presentation.email.EmailVorgangEinzelEmailCreateView;
import de.ivu.elect.presentation.exchange.ExchangeDescription;
import de.ivu.elect.presentation.exchange.ExportDescription;
import de.ivu.elect.presentation.exchange.ExportDescriptionSelect;
import de.ivu.elect.presentation.exchange.ExportView;
import de.ivu.elect.presentation.exchange.ExportViewConfirmDialog;
import de.ivu.elect.presentation.exchange.ExportViewResult;
import de.ivu.elect.presentation.gebietsbaum.GebietNummerFormatter;
import de.ivu.elect.presentation.hilfe.OnlineHilfeId;
import de.ivu.elect.presentation.mandant.MandantSessionSelect;
import de.ivu.elect.util.ThrowableUtil;

@OnlineHilfeId(value = "481", mehrfachVergebenOk = true)
public abstract class AbstractDokumentErzeugenView<E, C extends ElectDokumentContext> extends AbstractView implements ProgressView, ExportView<C>, ViewHavingFileUpload {

  private static final long serialVersionUID = 1L;

  private static final int MAX_ANZAHL_NACHRICHTEN = 20;

  @Inject
  protected transient WahlSessionSelector wahlSessionSelector;

  @Inject
  protected transient WahlterminSessionSelect wahlterminSessionSelect;

  @Inject
  protected transient GebietSessionSelect gebietSessionSelect;

  @Inject
  protected transient ImportExportStreamCreator streamCreator;

  @Inject
  protected transient DokumentVorlageExtendedDAO dokumentVorlageExtendedDAO;

  @Inject
  protected transient StartViewResolver startViewResolver;

  @Inject
  protected transient FileTypeResolver fileTypeResolver;

  @Inject
  protected transient ElectCommonPrincipal principal;

  @Inject
  protected transient DokumentGenerierenSupportedOpenOfficeFileFormats dokumentGenerierenSupportedOpenOfficeFileFormats;

  @Inject
  protected transient DokumentGenerierenProgressMonitor dokumentGenerierenProgressMonitor;

  @View
  @Inject
  protected transient EmailVorgangEinzelEmailCreateView emailVorgangEinzelEmailCreateView;

  @Inject
  protected transient DateiExportExtendedDAO dateiExportExtendedDAO;

  @Inject
  protected transient DateiExportEdit dateiExportEdit;

  @Inject
  protected transient DateiExportConversationSelect dateiExportConversationSelect;

  @View
  @Inject
  protected transient DateiExportSearchView dateiExportSearchView;

  @Inject
  protected transient ExportDescriptionSelect dateiExportDescriptionSelect;

  @Inject
  protected transient MandantSessionSelect mandantSessionSelect;

  @Inject
  protected transient GebietNummerFormatter gebietNummerFormatter;

  private final Logger log = LoggerFactory.getLogger(getClass());

  private List<E> entities;

  private FileType selectedFileType;

  private DokumentVorlage selectedDokumentVorlage;

  private String sourceViewId;

  private boolean generiereAlsEmailAnhang = false;

  protected volatile DateiExportPK dokumentGenerierenResult;

  protected volatile Future<DokumentErzeugenResult> dokumentGenerierenFuture;

  private AdvancedDynaFormModel dokumentParameterModel;

  private ExportViewConfirmDialog dokumentConfirmDialog;

  private List<DateiExport> dateiExportSearchResult = null;

  protected AbstractDokumentErzeugenView() {
    super();
  }

  public abstract String getViewId();

  @Nullable
  @PreConditionCheck
  public String checkPreCondition() {
    if (!isWahlSelected() && !isWahlterminSelected() || !isEntitiesSelected()) {
      return startViewResolver.getStartViewId();
    }

    if (selectedFileType == null) {
      selectedFileType = getDefaultFileType();

      if (selectedFileType == null) {
        selectedFileType = getSupportedFileTypes().get(0);
      }
    }

    return null;
  }

  @Nullable
  protected FileType getDefaultFileType() {
    return null;
  }

  protected boolean isWahlSelected() {
    return wahlSessionSelector.isSelected();
  }

  protected Wahl getSelectedWahl() {
    return wahlSessionSelector.getEntity();
  }

  protected boolean isWahlterminSelected() {
    return wahlterminSessionSelect.isSelected();
  }

  protected Wahltermin getSelectedWahltermin() {
    return wahlterminSessionSelect.getEntity();
  }

  public boolean isGebietSelected() {
    return gebietSessionSelect.isSelected();
  }

  protected Gebiet getSelectedGebiet() {
    return gebietSessionSelect.getEntity();
  }

  protected String getSelectedGebietNameFormatted() {
    return formatGebietName(getSelectedGebiet());
  }

  protected String formatGebietName(Gebiet gebiet) {
    return gebietNummerFormatter.getDarstellung(gebiet);
  }

  public void preRenderView() {
    checkDokumentVorlageVorhanden();
  }

  private void checkDokumentVorlageVorhanden() {
    if (isDokumentVorlagenVorhanden()) {
      if (getDokumentVorlagen().size() == 1) {
        selectedDokumentVorlage = getDokumentVorlagen().get(0);
      }
    } else {
      if (isDokumentVorlagenDirektHochladenMoeglich()) {
        addWarningMessage("dokument.vorlage.nicht.hinterlegt", getMessage(getDokumentVorlageArt()));
      } else {
        addErrorMessage("dokument.vorlage.nicht.hinterlegt", getMessage(getDokumentVorlageArt()));
      }

      selectedDokumentVorlage = null;
    }
  }

  public boolean isDokumentVorlagenVorhanden() {
    return !getDokumentVorlagen().isEmpty();
  }

  public boolean isDokumentParameterModelPresent() {
    return getDokumentParameterModel().isAnyPropertyAdded();
  }

  public AdvancedDynaFormModel getDokumentParameterModel() {
    if (dokumentParameterModel == null) {
      dokumentParameterModel = createDokumentParameterModel();
    }

    return dokumentParameterModel;
  }

  private AdvancedDynaFormModel createDokumentParameterModel() {
    FormBuilder formBuilder = new FormBuilder();
    addDokumentParameterProperties(formBuilder);

    return formBuilder.createModel();
  }

  protected void resetDokumentParameterModel() {
    dokumentParameterModel = null;
  }

  protected void addDokumentParameterProperties(FormBuilder formBuilder) {
    // To be overridden...
  }

  public ExportViewConfirmDialog getDokumentConfirmDialog() {
    if (dokumentConfirmDialog == null) {
      dokumentConfirmDialog = ExportViewConfirmDialog.UNSUPPORTED;
    }

    return dokumentConfirmDialog;
  }

  protected void setDokumentConfirmDialog(ExportViewConfirmDialog dokumentConfirmDialog) {
    this.dokumentConfirmDialog = dokumentConfirmDialog;
  }

  protected void resetDokumentConfirmDialog() {
    dokumentConfirmDialog = null;
  }

  public boolean isBtnGoBackDisabled() {
    return isGenerierungLaeuft() || isDownloadBereit();
  }

  @Redirect
  public String init(List<E> entities) {
    setEntities(entities);

    resetDokumentGenerieren();

    this.uploadedFile = null;
    this.generiereAlsEmailAnhang = false;
    this.sourceViewId = FacesContextUtil.getCurrentViewId();

    return getViewId();
  }

  @Redirect
  public String initAlsEmailAnhang(List<E> entities) {
    String viewId = init(entities);
    generiereAlsEmailAnhang = true;
    return viewId;
  }

  public boolean isGeneriereAlsEmailAnhang() {
    return generiereAlsEmailAnhang;
  }

  @Redirect
  public String anEmailAnhaengen() {
    return emailVorgangEinzelEmailCreateView.attachDocument(dateiExportExtendedDAO.findByPrimaryKey(dokumentGenerierenResult));
  }

  @Redirect
  public String erzeugeDokumentAlsEmailAnhang() {
    try {
      DokumentErzeugenResult result = erzeugeDokumentInternalSynchron(getContext());

      if (result.hasDokument()) {
        return emailVorgangEinzelEmailCreateView.attachDocumentByPk(result.getDokument());
      }

      return result.getTargetViewId();
    } catch (Exception ex) {
      if (ex.getLocalizedMessage().startsWith("com.artofsolving.jodconverter.openoffice.connection.OpenOfficeException")) {
        addErrorMessage("dokument.generierung.open.office.exception");
      }

      addErrorMessage(ex);
    }

    return getViewId();
  }

  @Override
  public boolean isSupportsFinaleKonvertierung(FileType fileType) {
    return fileType != null && getSupportedFileTypes().contains(fileType);
  }

  @Override // Cf. AbstractExportSearchView#export!!!
  public ExportViewResult export(FileFormat fileFormat, C context, @Nullable FileType finaleKonvertierung) {
    String viewId = getViewId();
    DokumentVorlageArt dokumentVorlageArt = getDokumentVorlageArt();

    FileFormat fileFormatExported = fileFormat;
    boolean finaleKonvertierungSupported = isSupportsFinaleKonvertierung(finaleKonvertierung);
    boolean finaleKonvertierungRequired = finaleKonvertierungSupported && finaleKonvertierung != null && !finaleKonvertierung.equals(fileFormatExported.getFileType());

    log.info("Export - start [view = {}, art = {}, format = {}, konvertierung = {}, konvertierung unterstuetzt = {}, konvertierung erforderlich = {}]", viewId, dokumentVorlageArt, fileFormat,
        finaleKonvertierung, finaleKonvertierungSupported, finaleKonvertierungRequired);

    if (finaleKonvertierungRequired) {
      fileFormatExported = new FileFormat(fileFormat.getName(), finaleKonvertierung);

      log.info("\tKonvertierung - format angepasst [from = {}, to = {}]", fileFormat, fileFormatExported);
    }

    setSelectedFileFormat(fileFormatExported);

    try {
      log.info("\tGenerierung - start");

      DokumentErzeugenResult result = erzeugeDokumentInternalSynchron(context);
      DateiExportPK dateiExportPk = result.getDateiExport().orElse(null);

      log.info("\tGenerierung - done [dateiExport = {}]", dateiExportPk);

      resetDokumentGenerieren();

      log.info("Export - done [dateiExport = {}]", dateiExportPk);

      return result;
    } catch (Exception ex) {
      log.warn("Export - fehlgeschlagen [view = {}, art = {}, format = {}, konvertierung = {}]", viewId, dokumentVorlageArt, fileFormat, finaleKonvertierung, ex);

      addErrorMessage("datei.export.action.exportieren.error.message", ThrowableUtil.getMessageDerUrsache(ex));
    }

    return Optional::empty;
  }

  @Redirect
  public String erzeugeDokument() {
    boolean confirmed = getDokumentConfirmDialog() == null || !getDokumentConfirmDialog().isRequired();

    if (confirmed) {
      return erzeugeDokumentConfirmed();
    }

    return FacesContextUtil.getCurrentViewId();
  }

  @Redirect
  public String erzeugeDokumentConfirmed() {
    resetDokumentConfirmDialog();

    try {
      return erzeugeDokumentInternalAsynchron(getContext());
    } catch (Exception ex) {
      onDokumentGenerierenFailed(ex);
    }

    return FacesContextUtil.getCurrentViewId();
  }

  @Nullable
  protected String erzeugeDokumentInternalAsynchron(C context) throws Exception {
    if (isGenerierungLaeuft()) {
      return null;
    }

    if (uploadedFile == null && selectedDokumentVorlage == null) {
      addErrorMessage("dokumentvorlage.auswaehlen.oder.hochladen");

      return getViewId();
    }

    dokumentGenerierenResult = null;
    dokumentGenerierenFuture = generiereDokument(context, true); // Cf. AbstractDokumentErzeugenView#poll!!!

    return null;
  }

  @Nonnull
  protected DokumentErzeugenResult erzeugeDokumentInternalSynchron(C context) throws Exception {
    if (isGenerierungLaeuft()) {
      return DokumentErzeugenResult.error(getViewId(), "dokument.generierung.laeuft.gerade");
    }

    if (uploadedFile == null && selectedDokumentVorlage == null) {
      return DokumentErzeugenResult.error(getViewId(), "dokumentvorlage.auswaehlen.oder.hochladen");
    }

    DokumentErzeugenResult result = generiereDokument(context, false).get();

    dokumentGenerierenResult = result.getDokument();
    dokumentGenerierenFuture = null;

    if (result.hasException()) {
      throw result.getException();
    }

    return DokumentErzeugenResult.success(dokumentGenerierenResult);
  }

  private Future<DokumentErzeugenResult> generiereDokument(C context, boolean async) {
    dokumentGenerierenProgressMonitor.reset();

    resetDokumentGenerieren();

    dokumentGenerierenProgressMonitor.progress(DokumentGenerierenProgress.STARTE_GENERIERUNG);

    AbstractDokumentGenerator<E, C> generator = getDokumentGenerator();

    List<E> dokumentEntities = new ArrayList<>();

    if (isEntitiesSelected()) {
      dokumentEntities.addAll(getEntities());
    }

    if (async) {
      return generator.generiereDokumentAsynchron(dokumentEntities, getSelectedDokumentVorlage(), getUploadedFile(), getSelectedFileType(), getSelectedWahl(), getSelectedWahltermin(), context,
          dokumentGenerierenProgressMonitor);
    }

    return generator.generiereDokumentSynchron(dokumentEntities, getSelectedDokumentVorlage(), getUploadedFile(), getSelectedFileType(), getSelectedWahl(), getSelectedWahltermin(), context,
        dokumentGenerierenProgressMonitor);
  }

  protected DefaultStreamedContent createStreamContent(DateiExport dateiExportParameter) {
    return dateiExportParameter.getDatei().getDefaultStreamedContent(streamCreator);
  }

  protected abstract C getContext();

  public FileFormat getSelectedFileFormat() {
    return asDefaultFileFormat(getSelectedFileType());
  }

  public void setSelectedFileFormat(FileFormat fileFormat) {
    setSelectedFileType(fileFormat.getFileType());
  }

  @Override
  public boolean isSupportedFileFormatsRendered() {
    return true;
  }

  @Override
  public List<FileFormat> getSupportedFileFormats() {
    return getSupportedFileTypes().stream().map(this::asDefaultFileFormat).collect(toList());
  }

  private FileFormat asDefaultFileFormat(FileType fileType) {
    return new FileFormat("", fileType);
  }

  public FileType getSelectedFileType() {
    return selectedFileType;
  }

  public void setSelectedFileType(FileType fileType) {
    this.selectedFileType = fileType;
  }

  public List<FileType> getSupportedFileTypes() {
    return dokumentGenerierenSupportedOpenOfficeFileFormats.getSupportedFileTypes();
  }

  public DokumentVorlage getSelectedDokumentVorlage() {
    return selectedDokumentVorlage;
  }

  public void setSelectedDokumentVorlage(DokumentVorlage selectedDokumentVorlage) {
    this.selectedDokumentVorlage = selectedDokumentVorlage;
  }

  public List<DokumentVorlage> getDokumentVorlagen() {
    if (isWahlSelected()) {
      return dokumentVorlageExtendedDAO.findByWahlAndArtOrderByName(getSelectedWahl(), getDokumentVorlageArt());
    }

    return dokumentVorlageExtendedDAO.findByWahlterminAndArtOrderByName(getSelectedWahltermin(), getDokumentVorlageArt());
  }

  public DokumentVorlageArt getDokumentVorlageArt() {
    return getDokumentGenerator().getDokumentVorlageArt();
  }

  protected boolean isEntitiesSelected() {
    return getEntities() != null; // ELECT-8512
  }

  @Nullable
  protected List<E> getEntities() {
    return entities;
  }

  public void setEntities(List<E> entities) {
    this.entities = entities;
  }

  protected abstract AbstractDokumentGenerator<E, C> getDokumentGenerator();

  @Redirect
  public String abbrechen() {
    return sourceViewId;
  }

  public boolean isBtnGenerierenRendered() {
    return hasUseCasePermission(getUseCasePermission());
  }

  public boolean isBtnGenerierenDisabled() {
    return isGenerierungLaeuft() || isDownloadBereit() || !isErzeugenMoeglich();
  }

  public boolean isErzeugenMoeglich() {
    return isBtnGenerierenRendered() && (isDokumentVorlagenVorhanden() || isDokumentVorlagenDirektHochladenMoeglich());
  }

  @Override
  public UseCasePermission getUseCasePermission() {
    return getRequiredPermission();
  }

  /**
   * @deprecated
   * @see AbstractDokumentErzeugenView#getUseCasePermission
   */
  @Deprecated
  protected abstract UseCasePermission getRequiredPermission();

  @Override
  public boolean isGenerierungLaeuft() {
    return dokumentGenerierenFuture != null;
  }

  public boolean isDownloadBereit() {
    return dokumentGenerierenResult != null;
  }

  @Override
  public void poll() {
    if (isGenerierungLaeuft()) {
      if (dokumentGenerierenFuture.isCancelled()) {
        onDokumentGenerierenFailed(null);
      } else if (dokumentGenerierenFuture.isDone()) {
        try {
          DokumentErzeugenResult result = dokumentGenerierenFuture.get();

          dokumentGenerierenResult = result.getDokument();
          dokumentGenerierenFuture = null;

          if (result.hasException()) {
            onDokumentGenerierenFailed(result.getException());
          }
        } catch (Exception ex) { // NOSONAR
          onDokumentGenerierenFailed(ex);
        }
      }
    }
  }

  protected void onDokumentGenerierenFailed(@Nullable Exception ex) {
    resetDokumentGenerieren();

    if (ex == null) {
      FacesMessageUtil.addErrorMessage("dokument.generieren.abgebrochen");
      FacesContextUtil.redirectToView(FacesContextUtil.getCurrentViewId());

      return;
    }

    log.warn("Erzeugen abgebrochen/fehlgeschlagen", ex);

    dokumentGenerierenProgressMonitor.addError("dokument.generieren.abgebrochen.exception", ex);
  }

  protected void resetDokumentGenerieren() {
    clearSelectedSearchResultEntry();

    resetSearchResult();

    resetDokumentConfirmDialog();

    dokumentGenerierenResult = null;
    dokumentGenerierenFuture = null;
  }

  @Override
  public List<String> getProgressMessages() {
    List<String> tempList = new ArrayList<>(dokumentGenerierenProgressMonitor.getProgressMessages());

    return tempList.subList(Math.max(0, tempList.size() - MAX_ANZAHL_NACHRICHTEN), tempList.size());
  }

  @Override
  public boolean isBtnCancelRendered() {
    return true;
  }

  @Override
  public void cancelProgress() {
    if (isGenerierungLaeuft()) {
      dokumentGenerierenProgressMonitor.getCancelRequested().set(true);
      dokumentGenerierenFuture.cancel(false);

      FacesMessageUtil.addInfoMessage("dokument.generieren.abgebrochen");
    }

    resetDokumentGenerieren();

    FacesContextUtil.redirectToView(FacesContextUtil.getCurrentViewId());
  }

  public StreamedContent getStreamedContent() {
    return getStreamedContent(dokumentGenerierenResult);
  }

  protected StreamedContent getStreamedContent(DateiExportPK dateiExportPK) {
    return createStreamContent(dateiExportExtendedDAO.findByPrimaryKey(dateiExportPK));
  }

  public StreamedContent getStreamedContent(DateiExport dateiExport) {
    return createStreamContent(dateiExportExtendedDAO.attach(dateiExport));
  }

  @Override
  public int getProgressBar() {
    return dokumentGenerierenProgressMonitor.getProgressBar().get();
  }

  @Override
  public boolean isModalDialogProgressVisible() {
    return isGenerierungLaeuft() || isDownloadBereit();
  }

  public boolean isDokumentVorlagenDirektHochladenMoeglich() {
    return principal.hasUseCasePermission(UseCasePermission.DOKUMENT_VORLAGE_DIREKT_HOCHLADEN);
  }

  private transient UploadedFile uploadedFile;

  @Override
  public void handleFileUpload(FileUploadEvent event) {
    setUploadedFile(new UploadedFileWithCanonicalFilename(event.getFile())); // ELECT-3038
  }

  @Override
  public String getFileUploadLabel() {
    return getMessage("datei.import.edit.action.upload.choose", fileTypeResolver.formatFileTypes(getFileUploadFileTypes()));
  }

  @Override
  public String getFileUploadAllowTypes() {
    return fileTypeResolver.getFileTypesHtmlRegEx(getFileUploadFileTypes());
  }

  @Override
  public String getFileUploadAccept() {
    return fileTypeResolver.getFileTypesHtmlAccept(getFileUploadFileTypes());
  }

  @Override
  public List<FileType> getFileUploadFileTypes() {
    return asList(FileType.ODT, FileType.ZIP, FileType.DVZ);
  }

  public UploadedFile getUploadedFile() {
    return uploadedFile;
  }

  public void setUploadedFile(UploadedFile uploadedFile) {
    this.uploadedFile = uploadedFile;
    this.selectedDokumentVorlage = null;
  }

  public String getVorlageNoSelectionLabel() {
    if (uploadedFile == null) {
      return getMessage("dokument.erzeugen.dokument.vorlage.no.selection.label");
    }

    return getMessage("dokument.erzeugen.dokument.vorlage.hochgeladen.no.selection.label");
  }

  @Inject // ELECT-3534 - WAS Dokumentenerzeugung: Nach Wechsel der Wahl muss die hochgeladene Vorlage gelöscht werden
  protected GroupedConversation conversation;

  public void onWahlSelectChangeEvent(@Observes(notifyObserver = Reception.IF_EXISTS) WahlSelectChangeEvent event) {
    reset();
  }

  public void onWahlterminSelectChangeEvent(@Observes(notifyObserver = Reception.IF_EXISTS) WahlterminSelectChangeEvent event) {
    reset();
  }

  public void onGebietSelectChangeEvent(@Observes(notifyObserver = Reception.IF_EXISTS) GebietSelectChangeEvent event) {
    reset();
  }

  public void reset() {
    resetDokumentGenerieren();

    resetDokumentParameterModel();

    conversation.close();
  }

  protected Mandant getMandant() {
    if (isWahlSelected()) {
      return getSelectedWahl().getMandant();
    }

    if (isWahlterminSelected()) {
      return getSelectedWahltermin().getMandant();
    }

    return mandantSessionSelect.getMandant();
  }

  protected boolean hasUseCasePermission(UseCasePermission useCasePermission) {
    return principal.hasUseCasePermission(useCasePermission);
  }

  @Override
  public boolean isSearchResultEntrySelected() {
    return dateiExportConversationSelect.isSelected();
  }

  @Override
  public DateiExport getSelectedSearchResultEntry() {
    return dateiExportConversationSelect.getEntity();
  }

  @Override
  public void setSelectedSearchResultEntry(DateiExport dateiExport) {
    dateiExportConversationSelect.setEntity(dateiExport);
  }

  protected void clearSelectedSearchResultEntry() {
    dateiExportConversationSelect.clearEntity();
  }

  @Override
  public boolean isSearchResultRendered() {
    return false;
  }

  @Override
  public List<DateiExport> getSearchResult() {
    ExportDescription exportDescription = new ExportDescription() {

      private static final long serialVersionUID = 1L;

      @Override
      public UseCasePermission getUseCasePermission() {
        return AbstractDokumentErzeugenView.this.getUseCasePermission();
      }

      @Override
      public String getExportSearchViewId() {
        return AbstractDokumentErzeugenView.this.getViewId();
      }

      @Override
      public String getPageMenuComponentName() {
        return ExchangeDescription.KEIN_PAGE_MENU;
      }

      @Override
      public DateiExportArt getDateiExportArt() {
        return getDokumentGenerator().getDateiExportArt();
      }

      @Override
      public boolean isSpecificPerWahl() {
        return true;
      }

      @Override
      public boolean isSpecificPerWahltermin() {
        return true;
      }
    };

    dateiExportDescriptionSelect.setExportDescription(exportDescription); // IMMER setzen, Voraussetzung bspw. für DateiExportDownloadAction!

    if (dateiExportSearchResult == null) {
      dateiExportSearchResult = loadSearchResult(exportDescription, getDokumentGenerator().getDateiExportPredicate());
    }

    return dateiExportSearchResult;
  }

  private List<DateiExport> loadSearchResult(ExportDescription exportDescription, Predicate<DateiExport> searchResultPredicate) {
    DateiExportSearchParameters dateiExportSearchParameters = dateiExportSearchView.getSearchParameters();
    dateiExportSearchParameters.reset();
    dateiExportSearchParameters.setExportDescription(exportDescription);
    dateiExportSearchParameters.setSearchResultPredicate(searchResultPredicate);

    dateiExportSearchView.resetSearchResult();

    return dateiExportSearchView.getSearchResult();
  }

  private void resetSearchResult() {
    dateiExportSearchResult = null;
  }

  @Override
  public boolean isBtnDeleteRendered() {
    return true;
  }

  @Override
  @Redirect
  public String delete() {
    callDelete(getSelectedSearchResultEntry());

    clearSelectedSearchResultEntry();

    addInfoMessage("entity.edit.action.delete.success.message", getMessage(DateiConstants.MESSAGE_KEY_ENTITY_EINZAHL));

    resetSearchResult();

    return FacesContextUtil.getCurrentViewId();
  }

  protected void callDelete(DateiExport dateiExport) {
    dateiExportEdit.delete(dateiExport);
  }
}
