
package de.ivu.elect.presentation.wahl.exchange;

import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.function.Predicate;

import javax.inject.Inject;

import de.ivu.elect.business.datei.boundary.DateiExportSearchParameters;
import de.ivu.elect.business.datei.entity.DateiExport;
import de.ivu.elect.business.dokumente.control.ElectDokumentContext;
import de.ivu.elect.business.exchange.control.FileFormat;
import de.ivu.elect.business.gebietsbaum.boundary.GebietExtendedDAO;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.system.boundary.NlSpecialBackgroundServiceRunning;
import de.ivu.elect.business.wahl.boundary.AbstractNlExportArtefaktNachSystemExportstatusBulkExporter;
import de.ivu.elect.business.wahl.boundary.NlExportArtefaktNachSystemExportstatus;
import de.ivu.elect.business.wahl.control.AbstractNlExportArtefaktNachSystemExportstatusExportContext;
import de.ivu.elect.business.wahl.control.NlExportArtefaktNachSystemExportstatusExportObject;
import de.ivu.elect.business.wahl.entity.AbstractWahlParameterLoader;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.jee.presentation.redirect.Redirect;
import de.ivu.elect.presentation.dokumente.ElectDokumentContextGenerator;
import de.ivu.elect.presentation.exchange.AbstractExportSearchView;
import de.ivu.elect.presentation.wahl.menu.NlExportArtefaktNachSystemExportstatusSearchExportMenuItemEntry;


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

public abstract class AbstractNlExportArtefaktNachSystemExportstatusBulkExportView
    extends
    AbstractExportSearchView<NlExportArtefaktNachSystemExportstatusExportObject, AbstractNlExportArtefaktNachSystemExportstatusExportContext> {

  private static final long serialVersionUID = 1L;

  @Inject
  private transient GebietExtendedDAO gebietExtendedDAO;

  @Inject
  private transient ElectDokumentContextGenerator electDokumentContextGenerator;

  @Inject
  private transient NlExportArtefaktNachSystemExportstatusSearchExportMenuItemEntry nlExportArtefaktNachSystemExportstatusSearchExportMenuItemEntry;

  @Inject
  private transient NlSpecialBackgroundServiceRunning nlSpecialBackgroundServiceRunning;

  private AbstractNlExportArtefaktNachSystemExportstatusExportContext context;

  private Collection<NlExportArtefaktNachSystemExportstatus> artefakteInDateiExport;

  protected AbstractNlExportArtefaktNachSystemExportstatusBulkExportView() {
    super();
  }

  public abstract void preRenderView();

  @Override
  public boolean isSupportedFileFormatsRendered() {
    return super.isSupportedFileFormatsRendered() && getSupportedFileFormats().size() != 1;
  }

  public String getPageTitle() {
    return getPageHeader();
  }

  public String getPageHeader() {
    String dateiExportName = getDateiExportName();

    String msgKey = dateiExportName + ".export.page.header"; // ELECT-10810

    if (!getMessages().isMessageKeyVorhanden(msgKey)) {
      msgKey = dateiExportName + ".export.label";

      if (!getMessages().isMessageKeyVorhanden(msgKey)) {
        msgKey = "entity.export.page.header";
      }
    }

    return getMessage(msgKey, getExportName());
  }

  public String getExportName() {
    return getMessage(getDateiExportName());
  }

  private String getDateiExportName() {
    return getExportDescription().getDateiExportName();
  }

  @Override
  public abstract AbstractNlExportArtefaktNachSystemExportstatusBulkExportDescription getExportDescription();

  @Override
  protected abstract AbstractNlExportArtefaktNachSystemExportstatusBulkExporter getExporter();

  @Override
  protected AbstractNlExportArtefaktNachSystemExportstatusExportContext getContext() {
    if (context == null) {

      context = createContext(electDokumentContextGenerator.createElectDokumentContext(), getWahlParameterLoader(), findGebieteDerWahl());
      context.setDateiExportNachSchrittImWahlprozess(getExportDescription().isDateiExportNachSchrittImWahlprozess());
    }

    return context;
  }

  private List<Gebiet> findGebieteDerWahl() {
    // ELECT-13914
    Wahl selectedWahl = getSelectedWahl();
    if (selectedWahl == null) {
      return Collections.emptyList();
    }
    return gebietExtendedDAO.findByWahl(selectedWahl);
  }

  protected abstract AbstractNlExportArtefaktNachSystemExportstatusExportContext createContext(ElectDokumentContext electDokumentContext, AbstractWahlParameterLoader wahlParameterLoader,
                                                                                               Collection<Gebiet> gebieteInWahl);

  protected void resetContext() {
    context = null;
    resetExportParameterModel(); // Wenn Context, dann auch DynaForm-Model...
  }

  @Override
  protected List<DateiExport> loadSearchResult(DateiExportSearchParameters dateiExportSearchParameters) {
    dateiExportSearchParameters.setSearchResultPredicate(getSearchResultPredicate(getSupportedFileFormats())); // ELECT-10277

    return super.loadSearchResult(dateiExportSearchParameters);
  }

  protected Predicate<? super DateiExport> getSearchResultPredicate(List<FileFormat> fileFormatsSupported) {
    if (fileFormatsSupported.size() == 1) {
      FileFormat fileFormat = fileFormatsSupported.get(0);

      return dateiExport -> dateiExport != null && dateiExport.getDatei() != null && Objects.equals(dateiExport.getDatei().getFileFormat(), fileFormat);
    }

    return Objects::nonNull;
  }

  @Override
  @Redirect
  public String exportierenConfirmed() {
    getContext().resetBeforeExport(); // ELECT-11350

    preSelectFileFormat(getSupportedFileFormats());

    // ELECT-13799
    nlSpecialBackgroundServiceRunning.waitForBackgroundService();

    String outcome = super.exportierenConfirmed();

    // ELECTVAPP-1616, ELECTVAPP-1591, weitere Information VOR dem Zurücksetzen des Context sichern...
    artefakteInDateiExport = new HashSet<>(getContext().getArtefakteInDateiExport());

    resetContext(); // ELECT-12891

    return outcome;
  }

  @Override
  public boolean isNeedsDownload() {
    return super.isNeedsDownload() && !isNeedsRedirectToDownloads();
  }

  public boolean isNeedsRedirectToDownloads() {
    return artefakteInDateiExport != null && artefakteInDateiExport.size() > 1;
  }

  public String getNeedsRedirectToDownloadsMessage() {
    if (isNeedsRedirectToDownloads()) {
      List<String> artefaktFileNames = artefakteInDateiExport.stream() //
          .map(NlExportArtefaktNachSystemExportstatus::getOriginalDateiname) //
          .sorted() //
          .collect(toList());

      return getMessage("dokument.nach.system.exportstatus.export.redirect.message", artefaktFileNames.size(), String.join(", ", artefaktFileNames),
          String.join(System.lineSeparator(), artefaktFileNames));
    }

    return "";
  }

  @Redirect
  public String redirectToDownloads() {
    reset();

    return nlExportArtefaktNachSystemExportstatusSearchExportMenuItemEntry.getTargetViewId();
  }

  @Override
  protected void reset() {
    super.reset();

    resetContext();

    artefakteInDateiExport = null;
  }
}
