
package de.ivu.elect.dokumente.ergebnis.gesamtergebnis;

import static java.util.Collections.emptyList;

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

import de.ivu.elect.business.ergebnis.control.gesamtergebnis.ErgebnisGesamtergebnisTabellarischDocumentExportContext;
import de.ivu.elect.dokumente.ergebnis.AbstractErgebnisTabellarischDocumentAufteiler;
import de.ivu.elect.util.ListUtil;

public class ErgebnisGesamtergebnisTabellarischDocumentAufteiler
    extends
      AbstractErgebnisTabellarischDocumentAufteiler<ErgebnisGesamtergebnisTabellarischDocumentExportContext, ErgebnisGesamtergebnisTabellarischDocument, ErgebnisGesamtergebnisTabellarischDocumentZeile> {

  public ErgebnisGesamtergebnisTabellarischDocumentAufteiler() {
    super();
  }

  @Override
  protected List<ErgebnisGesamtergebnisTabellarischDocument> createDocumentCopiesHavingMaxAnzahlSpalten(ErgebnisGesamtergebnisTabellarischDocument template,
      ErgebnisGesamtergebnisTabellarischDocumentExportContext context) {
    List<ErgebnisGesamtergebnisTabellarischDocument> result = new ArrayList<>();

    result.add(template);

    if (context.hasDokumentVorlageStimmen()) {
      result.addAll(createDocumentCopiesFuerDirektstimmenHavingMaxAnzahlSpaltenIfApplicable(template, context));
      result.addAll(createDocumentCopiesFuerListenstimmenHavingMaxAnzahlSpaltenIfApplicable(template, context));
    }

    return result;
  }

  private List<ErgebnisGesamtergebnisTabellarischDocument> createDocumentCopiesFuerDirektstimmenHavingMaxAnzahlSpaltenIfApplicable(ErgebnisGesamtergebnisTabellarischDocument template,
      ErgebnisGesamtergebnisTabellarischDocumentExportContext context) {
    if (context.getWahl().isWahlMitDirektkandidatengebieten()) {
      return createDocumentCopiesFuerStimmenHavingMaxAnzahlSpalten(context, template, ErgebnisGesamtergebnisTabellarischDocumentDokumentVorlageArt.DIREKTSTIMMEN_ERSTE_SEITE_ANDERS,
          ErgebnisGesamtergebnisTabellarischDocumentDokumentVorlageArt.DIREKTSTIMMEN);
    }

    return emptyList();
  }

  private List<ErgebnisGesamtergebnisTabellarischDocument> createDocumentCopiesFuerListenstimmenHavingMaxAnzahlSpaltenIfApplicable(ErgebnisGesamtergebnisTabellarischDocument template,
      ErgebnisGesamtergebnisTabellarischDocumentExportContext context) {
    if (context.getWahl().isWahlMitListengebieten()) {
      return createDocumentCopiesFuerStimmenHavingMaxAnzahlSpalten(context, template, ErgebnisGesamtergebnisTabellarischDocumentDokumentVorlageArt.LISTENSTIMMEN_ERSTE_SEITE_ANDERS,
          ErgebnisGesamtergebnisTabellarischDocumentDokumentVorlageArt.LISTENSTIMMEN);
    }

    return emptyList();
  }

  private List<ErgebnisGesamtergebnisTabellarischDocument> createDocumentCopiesFuerStimmenHavingMaxAnzahlSpalten(ErgebnisGesamtergebnisTabellarischDocumentExportContext context,
      ErgebnisGesamtergebnisTabellarischDocument template, ErgebnisGesamtergebnisTabellarischDocumentDokumentVorlageArt dokumentVorlageArtErsteSeiteStimmen,
      ErgebnisGesamtergebnisTabellarischDocumentDokumentVorlageArt dokumentVorlageArtWeitereSeitenStimmen) {
    List<ErgebnisGesamtergebnisTabellarischDocument> result = new ArrayList<>();

    ErgebnisGesamtergebnisTabellarischDocument copy = template;
    List<Integer> anzahlSpaltenJeStimmenTeil = berechneAnzahlSpaltenJeDokumentVorlageArten(template, context);

    copy = copy.copy(dokumentVorlageArtErsteSeiteStimmen);
    result.add(copy);

    for (int i = 0; i < anzahlSpaltenJeStimmenTeil.size() - 1; i++) {
      Integer anzahlSpalten = anzahlSpaltenJeStimmenTeil.get(i);

      copy = copy.copy(dokumentVorlageArtWeitereSeitenStimmen);
      copy.removeAnzahlParteiEintraege(anzahlSpalten);

      result.add(copy);
    }

    return result;
  }

  @Override
  protected List<Integer> berechneAnzahlSpaltenJeDokumentVorlageArten(ErgebnisGesamtergebnisTabellarischDocument template, ErgebnisGesamtergebnisTabellarischDocumentExportContext context) {
    return berechneAnzahlSpaltenJeDokumentVorlageArten(extractAnzahlSpalten(template), context.getDokumentVorlageErsteSeiteAnzahlSpalten(), context.getDokumentVorlageWeitereSeitenAnzahlSpalten(),
        context.getDokumentVorlageWeitereSeitenDirektstimmen(), context.getDokumentVorlageWeitereSeitenListenstimmen());
  }

  private int extractAnzahlSpalten(ErgebnisGesamtergebnisTabellarischDocument template) {
    if (template.zeilen.isEmpty()) {
      return template.parteiStimmenSummeQueueAnzahlZweitstimmen.size();
    }

    return template.zeilen.get(0).parteiStimmenQueueAnzahlErststimmen.size();
  }

  @Override
  protected List<ErgebnisGesamtergebnisTabellarischDocument> createDocumentCopiesHavingZeilen(ErgebnisGesamtergebnisTabellarischDocument template,
      List<List<ErgebnisGesamtergebnisTabellarischDocumentZeile>> zeilenPerDocumentCopy) {
    List<ErgebnisGesamtergebnisTabellarischDocument> result = new ArrayList<>();

    for (List<ErgebnisGesamtergebnisTabellarischDocumentZeile> zeilen : zeilenPerDocumentCopy) {
      ErgebnisGesamtergebnisTabellarischDocument copy = template.copy();
      copy.ergebnisSummen = null;

      copy.zeilen.clear();
      copy.zeilen.addAll(zeilen);

      result.add(copy);
    }

    return result;
  }

  @Override
  protected void calculateDocumentsUebertraegeAndSummen(List<ErgebnisGesamtergebnisTabellarischDocument> documents, List<ErgebnisGesamtergebnisTabellarischDocumentZeile> alleZeilenInDocuments) {
    calculateSummeAufLetzterSeiteOderDatenAufZwischenseiten(documents, alleZeilenInDocuments);
  }

  private void calculateSummeAufLetzterSeiteOderDatenAufZwischenseiten(List<ErgebnisGesamtergebnisTabellarischDocument> documents,
      List<ErgebnisGesamtergebnisTabellarischDocumentZeile> alleZeilenInDocuments) {
    ErgebnisGesamtergebnisTabellarischDocument lastDocument = ListUtil.lastOrNull(documents);

    for (ErgebnisGesamtergebnisTabellarischDocument document : documents) {
      document.parteiStimmenSummeQueueNummer.clear();
      document.parteiStimmenSummeQueueKennung.clear();
      document.parteiStimmenSummeQueueNameGruppe.clear();
      document.parteiStimmenSummeQueueNameDirektkandidat.clear();
      document.parteiStimmenSummeQueueAnzahlErststimmen.clear();
      document.parteiStimmenSummeQueueAnzahlZweitstimmen.clear();

      document.berechnenSummen(alleZeilenInDocuments);
      document.berechneUeberschriftenQueue();
      document.ergebnisSummen = null; // FIXME WTF: Erst Summen setzen und dann löschen ?
      document.parteiStimmenSummeQueueAnzahlErststimmen.clear(); // FIXME WTF: Zweimal clear() ??
      document.parteiStimmenSummeQueueAnzahlZweitstimmen.clear();

      if (document.equals(lastDocument)) {
        document.berechnenSummen(alleZeilenInDocuments);
        document.berechneUeberschriftenQueue(); // FIXME WTF: Nochmal berechnen ???
      } else {
        // Nicht zu tun... ???
      }
    }
  }
}
