
package de.ivu.elect.presentation.verteilung;

import static java.util.Collections.emptyList;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;

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

import de.ivu.elect.business.verteilung.boundary.VerteilungContext;
import de.ivu.elect.business.verteilung.boundary.VerteilungTeilnehmer;
import de.ivu.elect.business.verteilung.boundary.VerteilungTeilnehmerErgebnis;
import de.ivu.elect.business.verteilung.boundary.VerteilungZuteilungsdivisorBerechnungSchritt;
import de.ivu.elect.jee.presentation.dynamicform.AdvancedDynaFormModel;
import de.ivu.elect.jee.presentation.dynamictable.AbstractColumnBuilder;
import de.ivu.elect.presentation.verteilung.table.AbstractVerteilungBerechnenViewZuteilungsdivisorResultColumnBuilder;

public class VerteilungBerechnenViewZuteilungsdivisorResult extends AbstractVerteilungBerechnenViewResult {

  private final AbstractVerteilungBerechnenViewZuteilungsdivisorResultColumnBuilder verteilungBerechnenViewDivisorColumnBuilder;

  private final AbstractVerteilungBerechnenViewZuteilungsdivisorResultColumnBuilder verteilungBerechnenViewDivisorkandidatColumnBuilder;

  public VerteilungBerechnenViewZuteilungsdivisorResult(VerteilungBerechnenViewContext context, VerteilungBerechnenViewErgebnis ergebnis,
      AbstractVerteilungBerechnenViewZuteilungsdivisorResultColumnBuilder verteilungBerechnenViewDivisorColumnBuilder,
      AbstractVerteilungBerechnenViewZuteilungsdivisorResultColumnBuilder verteilungBerechnenViewDivisorkandidatColumnBuilder) {
    super(context, ergebnis);

    this.verteilungBerechnenViewDivisorColumnBuilder = verteilungBerechnenViewDivisorColumnBuilder;

    this.verteilungBerechnenViewDivisorkandidatColumnBuilder = verteilungBerechnenViewDivisorkandidatColumnBuilder;
  }

  public List<VerteilungBerechnenViewZuteilungsdivisorSchritt> getSchritte() {
    List<VerteilungBerechnenViewZuteilungsdivisorSchritt> result = new ArrayList<>();

    getErgebnis().ifPresent(ergebnis -> {
      VerteilungContext context = ergebnis.getContext();

      ergebnis.getZuteilungsdivisor().ifPresent(zuteilungsdivisor -> {
        for (VerteilungZuteilungsdivisorBerechnungSchritt zuteilungsdivisorBerechnungSchritt : zuteilungsdivisor.getDivisorBerechnungSchritte()) {
          result.add(new VerteilungBerechnenViewZuteilungsdivisorSchritt(context, zuteilungsdivisorBerechnungSchritt));
        }
      });
    });

    return result;
  }

  public class VerteilungBerechnenViewZuteilungsdivisorSchritt {

    private final VerteilungContext context;

    private final VerteilungZuteilungsdivisorBerechnungSchritt zuteilungsdivisorBerechnungSchritt;

    private final List<VerteilungBerechnenViewTeilnehmerErgebnis> teilnehmerErgebnisse;

    private final List<VerteilungBerechnenViewTeilnehmerErgebnis> divisorkandidaten;

    public VerteilungBerechnenViewZuteilungsdivisorSchritt(VerteilungContext context, VerteilungZuteilungsdivisorBerechnungSchritt zuteilungsdivisorBerechnungSchritt) {
      super();

      this.context = context;

      this.zuteilungsdivisorBerechnungSchritt = zuteilungsdivisorBerechnungSchritt;

      this.teilnehmerErgebnisse = zuteilungsdivisorBerechnungSchritt.collectTeilnehmerErgebnisse().stream()
          .map(teilnehmerErgebnis -> new VerteilungBerechnenViewTeilnehmerErgebnis(context, teilnehmerErgebnis, teilnehmerErgebnis.getQuotienten())).collect(toList());

      this.divisorkandidaten = zuteilungsdivisorBerechnungSchritt.collectDivisorkandidaten().stream()
          .map(teilnehmerErgebnis -> new VerteilungBerechnenViewTeilnehmerErgebnis(context, teilnehmerErgebnis, teilnehmerErgebnis.getQuotienten())).collect(toList());
    }

    public boolean isHeaderRendered() {
      return getTeilnehmerErgebnisseModel().isAnyPropertyAdded();
    }

    public String getHeader() {
      if (zuteilungsdivisorBerechnungSchritt.isSchrittInIteration()) {
        String msgKeyPrefix = "verteilung.berechnen.ergebnis.zuteilungsdivisor.header.iteration.";

        if (zuteilungsdivisorBerechnungSchritt.isSchrittInIterationInitial()) {
          return context.getMessage(msgKeyPrefix + "anfangsdivisor");
        }

        return context.getMessage(msgKeyPrefix + "divisor");
      }

      return "";
    }

    public boolean isBeschreibungModelRendered() {
      return getBeschreibungModel().isAnyPropertyAdded();
    }

    public AdvancedDynaFormModel getBeschreibungModel() {
      return createResultModel(zuteilungsdivisorBerechnungSchritt.formatBeschreibung(context));
    }

    public List<VerteilungBerechnenViewTeilnehmerErgebnis> getTeilnehmerErgebnisse() {
      List<VerteilungBerechnenViewTeilnehmerErgebnis> result = new ArrayList<>();
      result.addAll(teilnehmerErgebnisse);

      if (!result.isEmpty()) { // Summenzeile
        String key = "summe@" + System.nanoTime();
        String label = context.getMessage("VerteilungBerechnenViewTeilnehmerErgebnisAnzahlSitzeAnspruchColumn.summe");

        VerteilungTeilnehmer teilnehmer = new VerteilungTeilnehmer(result.size(), key, label);
        teilnehmer.setAnzahlStimmen(Long.MIN_VALUE); // Anzahl negativ -> KEINE Ausgabe bspw. in Tabellenspalte...

        result.add(new VerteilungBerechnenViewTeilnehmerErgebnis(context, new VerteilungTeilnehmerErgebnis(teilnehmer, zuteilungsdivisorBerechnungSchritt.getAnzahlSitzeVerteilt(), emptyList()),
            emptyList()));
      }

      return result;
    }

    public String getTeilnehmerErgebnisseBemerkung() {
      return verteilungBerechnenViewDivisorColumnBuilder.collectColumnTooltips(teilnehmerErgebnisse).stream().collect(joining(", "));
    }

    public AbstractColumnBuilder<VerteilungBerechnenViewTeilnehmerErgebnis> getTeilnehmerErgebnisseColumnBuilder() {
      return verteilungBerechnenViewDivisorColumnBuilder;
    }

    public boolean isTeilnehmerErgebnisseModelRendered() {
      return getTeilnehmerErgebnisseModel().isAnyPropertyAdded();
    }

    public AdvancedDynaFormModel getTeilnehmerErgebnisseModel() {
      return createResultModel(zuteilungsdivisorBerechnungSchritt.formatTeilnehmerErgebnisseBeschreibung(context));
    }

    public List<VerteilungBerechnenViewTeilnehmerErgebnis> getDivisorkandidaten() {
      List<VerteilungBerechnenViewTeilnehmerErgebnis> result = new ArrayList<>();
      result.addAll(divisorkandidaten);

      return result;
    }

    public String getDivisorkandidatenBemerkung() {
      return verteilungBerechnenViewDivisorkandidatColumnBuilder.collectColumnTooltips(divisorkandidaten).stream().collect(joining(", "));
    }

    public AbstractColumnBuilder<VerteilungBerechnenViewTeilnehmerErgebnis> getDivisorkandidatenColumnBuilder() {
      return verteilungBerechnenViewDivisorkandidatColumnBuilder;
    }

    public boolean isDivisorkandidatenModelRendered() {
      return getDivisorkandidatenModel().isAnyPropertyAdded();
    }

    public AdvancedDynaFormModel getDivisorkandidatenModel() {
      return createResultModel(zuteilungsdivisorBerechnungSchritt.formatDivisorkandidatenBeschreibung(context));
    }
  }
}
