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

import static de.ivu.elect.jee.entity.EntityUtil.castTo;
import static java.util.Arrays.asList;

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

import de.ivu.elect.business.dokumente.entity.DokumentVorlage;
import de.ivu.elect.business.dokumente.entity.DokumentVorlageArt;
import de.ivu.elect.business.ergebnis.boundary.AbstractErgebnisDAO;
import de.ivu.elect.business.ergebnis.boundary.ErgebnisdokumentTyp;
import de.ivu.elect.business.ergebnis.boundary.ErgebnisdokumentTypPerWahlartResolver;
import de.ivu.elect.business.ergebnis.control.ErgebnisExchangeContext;
import de.ivu.elect.business.ergebnis.entity.Ergebnis;
import de.ivu.elect.business.exchange.control.FileFormat;
import de.ivu.elect.business.gebietsbaum.boundary.AbstractGebietDAO;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.kandidatur.control.StimmzettelFormatterKandidaturFormatDarstellung;
import de.ivu.elect.business.security.UseCasePermission;
import de.ivu.elect.business.wahl.entity.Wahldurchfuehrung;
import de.ivu.elect.presentation.dokumente.exchange.AbstractDokumentBulkExportSubView;
import de.ivu.elect.presentation.dokumente.exchange.DokumentBulkExportSearchEntry;
import de.ivu.elect.presentation.exchange.ExportView;

public abstract class AbstractErgebnisdokumentBulkExportSubView<F extends ErgebnisdokumentBulkExportDokumentVorlageFilter, T extends ExportView<C>, C>
    extends
      AbstractDokumentBulkExportSubView<Wahldurchfuehrung, T, C> {

  private static final String DOKUMENT_VORLAGE_NAME_INFIX_STIMMEN = ErgebnisdokumentBulkExportDokumentVorlageFilter.DOKUMENT_VORLAGE_NAME_INFIX_STIMMENART_STIMMEN;

  private static final String DOKUMENT_VORLAGE_NAME_INFIX_DIREKTSTIMMEN = ErgebnisdokumentBulkExportDokumentVorlageFilter.DOKUMENT_VORLAGE_NAME_INFIX_STIMMENART_DIREKTSTIMMEN;

  private static final String DOKUMENT_VORLAGE_NAME_INFIX_LISTENSTIMMEN = ErgebnisdokumentBulkExportDokumentVorlageFilter.DOKUMENT_VORLAGE_NAME_INFIX_STIMMENART_LISTENSTIMMEN;

  private static final String DOKUMENT_VORLAGE_NAME_INFIX_ERSTE_SEITE = ErgebnisdokumentBulkExportDokumentVorlageFilter.DOKUMENT_VORLAGE_NAME_INFIX_SEITENART_ERSTE_SEITE;

  private static final String DOKUMENT_VORLAGE_NAME_INFIX_WEITERE_SEITEN = ErgebnisdokumentBulkExportDokumentVorlageFilter.DOKUMENT_VORLAGE_NAME_INFIX_SEITENART_WEITERE_SEITEN;

  protected static final String DOKUMENT_VORLAGE_BESCHREIBUNG_FORMAT = "Dokumentvorlage %s";

  protected static final String DOKUMENT_VORLAGE_BESCHREIBUNG_FORMAT_ANZAHL_ZEILEN_UND_SPALTEN = "Dokumentvorlage %s mit %d Spalten und maximal %d Zeilen pro Seite";

  protected static final String DOKUMENT_VORLAGE_BESCHREIBUNG_FORMAT_ANZAHL_ZEILEN = "Dokumentvorlage %s mit maximal %d Zeilen pro Seite";

  private final AbstractGebietDAO gebietDAO;

  private final Collection<Gebiet> auswertungsgebiete;

  private final ErgebnisdokumentTypPerWahlartResolver ergebnisdokumentTypPerWahlartResolver;

  private final ErgebnisdokumentTyp ergebnisdokumentTyp;

  private final AbstractErgebnisDAO ergebnisDAO;

  private final Ergebnis ergebnis;

  private final StimmzettelFormatterKandidaturFormatDarstellung kandidaturFormatDarstellung;

  private final DokumentVorlageArt dokumentVorlageArt;

  private final F dokumentVorlageFilter;

  protected AbstractErgebnisdokumentBulkExportSubView(T exportView, ErgebnisdokumentBulkExportSubViewContext context, DokumentVorlageArt dokumentVorlageArt, F dokumentVorlageFilter) {
    super(exportView, context.getErgebnisdokumentTyp(), context.getMessages(), context.getDokumentVorlageDAO());

    this.gebietDAO = context.getGebietDAO();
    this.auswertungsgebiete = context.getAuswertungsgebiete();

    this.ergebnisdokumentTypPerWahlartResolver = context.getErgebnisdokumentTypPerWahlartResolver();
    this.ergebnisdokumentTyp = context.getErgebnisdokumentTyp();

    this.ergebnisDAO = context.getErgebnisDAO();
    this.ergebnis = context.getErgebnis();

    this.kandidaturFormatDarstellung = context.getKandidaturFormatDarstellung();

    this.dokumentVorlageArt = dokumentVorlageArt;
    this.dokumentVorlageFilter = dokumentVorlageFilter;
  }

  protected ErgebnisdokumentTyp getErgebnisdokumentTyp() {
    return ergebnisdokumentTyp;
  }

  @Override
  protected Collection<UseCasePermission> getUseCasePermissions() {
    return asList( //
        UseCasePermission.DOKUMENT_ERZEUGEN_BULK_EXPORT_ERGEBNISDOKUMENTE // ELECT-8589, Minimalrecht
    );
  }

  @Override
  public boolean isExportEnabled() {
    return ergebnisdokumentTypPerWahlartResolver.isErgebnisartSupported(getErgebnis(), getErgebnisdokumentTyp());
  }

  protected Wahldurchfuehrung getWahl() {
    return castTo(getErgebnis().getWahl(), Wahldurchfuehrung.class);
  }

  protected Collection<Gebiet> getAuswertungsgebiete() {
    return gebietDAO.attachAll(auswertungsgebiete);
  }

  public Ergebnis getErgebnis() {
    return ergebnisDAO.attach(ergebnis);
  }

  protected StimmzettelFormatterKandidaturFormatDarstellung getKandidaturFormatDarstellung() {
    return kandidaturFormatDarstellung;
  }

  protected DokumentVorlageArt getDokumentVorlageArt() {
    return dokumentVorlageArt;
  }

  protected F getDokumentVorlageFilter() {
    return dokumentVorlageFilter;
  }

  protected String formatDokumentVorlageNameStimmen(Wahldurchfuehrung wahldurchfuehrung) {
    return formatDokumentVorlageName(wahldurchfuehrung, DOKUMENT_VORLAGE_NAME_INFIX_STIMMEN);
  }

  protected String formatDokumentVorlageNameErsteSeite(Wahldurchfuehrung wahldurchfuehrung) {
    return formatDokumentVorlageName(wahldurchfuehrung, DOKUMENT_VORLAGE_NAME_INFIX_ERSTE_SEITE);
  }

  protected String formatDokumentVorlageNameErsteSeiteStimmen(Wahldurchfuehrung wahldurchfuehrung) {
    return formatDokumentVorlageName(wahldurchfuehrung, DOKUMENT_VORLAGE_NAME_INFIX_STIMMEN, DOKUMENT_VORLAGE_NAME_INFIX_ERSTE_SEITE);
  }

  protected String formatDokumentVorlageNameErsteSeiteDirektstimmen(Wahldurchfuehrung wahldurchfuehrung) {
    return formatDokumentVorlageName(wahldurchfuehrung, DOKUMENT_VORLAGE_NAME_INFIX_DIREKTSTIMMEN, DOKUMENT_VORLAGE_NAME_INFIX_ERSTE_SEITE);
  }

  protected String formatDokumentVorlageNameErsteSeiteListenstimmen(Wahldurchfuehrung wahldurchfuehrung) {
    return formatDokumentVorlageName(wahldurchfuehrung, DOKUMENT_VORLAGE_NAME_INFIX_LISTENSTIMMEN, DOKUMENT_VORLAGE_NAME_INFIX_ERSTE_SEITE);
  }

  protected String formatDokumentVorlageNameWeitereSeiten(Wahldurchfuehrung wahldurchfuehrung) {
    return formatDokumentVorlageName(wahldurchfuehrung, DOKUMENT_VORLAGE_NAME_INFIX_WEITERE_SEITEN);
  }

  protected String formatDokumentVorlageNameWeitereSeitenStimmen(Wahldurchfuehrung wahldurchfuehrung) {
    return formatDokumentVorlageName(wahldurchfuehrung, DOKUMENT_VORLAGE_NAME_INFIX_STIMMEN, DOKUMENT_VORLAGE_NAME_INFIX_WEITERE_SEITEN);
  }

  protected String formatDokumentVorlageNameWeitereSeitenDirektstimmen(Wahldurchfuehrung wahldurchfuehrung) {
    return formatDokumentVorlageName(wahldurchfuehrung, DOKUMENT_VORLAGE_NAME_INFIX_DIREKTSTIMMEN, DOKUMENT_VORLAGE_NAME_INFIX_WEITERE_SEITEN);
  }

  protected String formatDokumentVorlageNameWeitereSeitenListenstimmen(Wahldurchfuehrung wahldurchfuehrung) {
    return formatDokumentVorlageName(wahldurchfuehrung, DOKUMENT_VORLAGE_NAME_INFIX_LISTENSTIMMEN, DOKUMENT_VORLAGE_NAME_INFIX_WEITERE_SEITEN);
  }

  protected String formatDokumentVorlageName(Wahldurchfuehrung wahldurchfuehrung, String... dokumentVorlageNameInfixes) {
    return "\u201E" + createDokumentVorlageName(wahldurchfuehrung, dokumentVorlageNameInfixes) + "\u201C";
  }

  private String createDokumentVorlageName(Wahldurchfuehrung wahldurchfuehrung, String... dokumentVorlageNameInfixes) {
    return getErgebnisdokumentTyp().createDokumentVorlageName(wahldurchfuehrung, wahldurchfuehrung.getWahltermin(), getMessages(), getDokumentVorlageArt(), dokumentVorlageNameInfixes);
  }

  @Override
  public List<DokumentBulkExportSearchEntry> collectDokumentBulkExportSearchEntries() {
    return collectDokumentBulkExportSearchEntries(getWahl(), getFileFormats());
  }

  protected abstract List<DokumentBulkExportSearchEntry> collectDokumentBulkExportSearchEntries(Wahldurchfuehrung wahldurchfuehrung, List<FileFormat> fileFormats);

  @Override
  protected C createExportContext(DokumentBulkExportSearchEntry dokumentBulkExportSearchEntry) {
    return createExportContext(new ErgebnisExchangeContext(getWahl(), new ArrayList<>(getAuswertungsgebiete()), getKandidaturFormatDarstellung()), getErgebnis(), dokumentBulkExportSearchEntry,
        new ArrayList<>(attach(dokumentBulkExportSearchEntry.getDokumentVorlagen())));
  }

  protected abstract C createExportContext(ErgebnisExchangeContext ergebnisExchangeContext, Ergebnis ergebnis, DokumentBulkExportSearchEntry dokumentBulkExportSearchEntry,
      List<DokumentVorlage> dokumentVorlagen);
}
