
package de.ivu.elect.presentation.kandidatur.table;

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

import javax.inject.Inject;
import javax.inject.Named;

import de.ivu.elect.business.ergebnis.entity.Ergebnis;
import de.ivu.elect.business.gebietsbaum.entity.Wahldurchfuehrungsgebiet;
import de.ivu.elect.business.kandidatur.boundary.KandidaturExtendedDAO;
import de.ivu.elect.business.kandidatur.entity.KandidaturKumulierteStimmen;
import de.ivu.elect.business.stimmeingabe.control.ListenwahlStimmeingabeKonfiguration;
import de.ivu.elect.business.stimmeingabe.control.StimmeingabeStimmenartLabelGenerator;
import de.ivu.elect.business.wahl.entity.WahlParameterLoader;
import de.ivu.elect.jee.presentation.dynamictable.ColumnEntry;
import de.ivu.elect.presentation.table.AbstractColumnEntry;

@Named(ListenkandidaturKumulierteStimmenColumnBuilder.COMPONENT_NAME)
public class ListenkandidaturKumulierteStimmenColumnBuilder extends AbstractKandidaturKumulierteStimmenColumnBuilder<KandidaturKumulierteStimmen> {

  private static final long serialVersionUID = 1L;

  public static final String COMPONENT_NAME = "listenkandidaturKumulierteStimmenColumnBuilder";

  @Inject
  private transient WahlParameterLoader wahlParameterLoader;

  @Inject
  private transient KandidaturExtendedDAO kandidaturExtendedDAO;

  @Inject
  private transient ListenwahlStimmeingabeKonfiguration listenwahlStimmeingabeKonfiguration;

  protected AbstractColumnEntry<KandidaturKumulierteStimmen> kandidaturKumulierteStimmenStimmzettelPositionColumn;

  private AbstractColumnEntry<KandidaturKumulierteStimmen> kandidaturKumulierteStimmenAnzahlDirektstimmenColumn;

  private AbstractColumnEntry<KandidaturKumulierteStimmen> kandidaturKumulierteStimmenGewaehltRangDirektstimmenColumn;

  protected AbstractColumnEntry<KandidaturKumulierteStimmen> kandidaturKumulierteStimmenAnzahlListenstimmenColumn;

  private AbstractColumnEntry<KandidaturKumulierteStimmen> kandidaturKumulierteStimmenAnzahlListenstimmenAnteilAusEinzelstimmvergabeColumn;

  private AbstractColumnEntry<KandidaturKumulierteStimmen> kandidaturKumulierteStimmenAnzahlListenstimmenAnteilAusWahlvorschlagstimmvergabeColumn;

  protected AbstractColumnEntry<KandidaturKumulierteStimmen> kandidaturKumulierteStimmenGewaehltRangListenstimmenColumn;

  private AbstractColumnEntry<KandidaturKumulierteStimmen> kandidaturKumulierteStimmenAnzahlGesamtstimmenColumn;

  private AbstractColumnEntry<KandidaturKumulierteStimmen> kandidaturKumulierteStimmenGewaehltRangGesamtstimmenColumn;

  public ListenkandidaturKumulierteStimmenColumnBuilder() {
    super();
  }

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

    kandidaturKumulierteStimmenStimmzettelPositionColumn = new KandidaturKumulierteStimmenStimmzettelPositionColumn(getMessages());

    if (isGebietSelected() && isErgebnisSelected()) {
      Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet = getSelectedGebiet();
      Ergebnis ergebnis = getSelectedErgebnis();

      boolean wahlMitDirektwahlgebietenSelected = isWahlMitDirektwahlgebietenSelected();
      boolean wahlMitListenwahlgebietenSelected = isWahlMitListenwahlgebietenSelected();

      boolean stimmenartenUnterscheiden = wahlMitDirektwahlgebietenSelected && wahlMitListenwahlgebietenSelected;

      StimmeingabeStimmenartLabelGenerator stimmenartLabelGenerator = getStimmenartLabelGenerator(wahldurchfuehrungsgebiet);

      if (wahlMitDirektwahlgebietenSelected) {
        kandidaturKumulierteStimmenAnzahlDirektstimmenColumn = new KandidaturKumulierteStimmenAnzahlDirektstimmenColumn(wahldurchfuehrungsgebiet, stimmenartenUnterscheiden, getMessages(),
            stimmenartLabelGenerator);
        kandidaturKumulierteStimmenGewaehltRangDirektstimmenColumn = new KandidaturKumulierteStimmenGewaehltRangDirektstimmenColumn(wahldurchfuehrungsgebiet,
            ergebnis, getMessages(), kandidaturExtendedDAO);
      }

      if (wahlMitListenwahlgebietenSelected) {
        kandidaturKumulierteStimmenAnzahlListenstimmenColumn = new KandidaturKumulierteStimmenAnzahlListenstimmenColumn(wahldurchfuehrungsgebiet, stimmenartenUnterscheiden, getMessages(), getIcons(),
            stimmenartLabelGenerator);

        if (isStimmzettelNurEinzelnerWahlvorschlagUnveraendertRelevant(ergebnis)) {
          kandidaturKumulierteStimmenAnzahlListenstimmenAnteilAusEinzelstimmvergabeColumn = new KandidaturKumulierteStimmenAnzahlListenstimmenAnteilAusEinzelstimmvergabeColumn(
              wahldurchfuehrungsgebiet, stimmenartenUnterscheiden, getMessages(), stimmenartLabelGenerator);
          kandidaturKumulierteStimmenAnzahlListenstimmenAnteilAusWahlvorschlagstimmvergabeColumn = new KandidaturKumulierteStimmenAnzahlListenstimmenAnteilAusWahlvorschlagstimmvergabeColumn(
              wahldurchfuehrungsgebiet, stimmenartenUnterscheiden, getMessages(), stimmenartLabelGenerator);
        }

        kandidaturKumulierteStimmenGewaehltRangListenstimmenColumn = new KandidaturKumulierteStimmenGewaehltRangListenstimmenColumn(wahldurchfuehrungsgebiet,
            ergebnis, getMessages(), kandidaturExtendedDAO);
      }

      if (isWahlMitGesamtstimmenauswertungSelected()) {
        kandidaturKumulierteStimmenAnzahlGesamtstimmenColumn = new KandidaturKumulierteStimmenAnzahlGesamtstimmenColumn(getMessages());
        kandidaturKumulierteStimmenGewaehltRangGesamtstimmenColumn = new KandidaturKumulierteStimmenGewaehltRangGesamtstimmenColumn(wahldurchfuehrungsgebiet,
            ergebnis, getMessages(), kandidaturExtendedDAO);
      }
    }
  }

  @Override
  public List<ColumnEntry< ? super KandidaturKumulierteStimmen>> getColumnEntriesSorted() {
    List<ColumnEntry< ? super KandidaturKumulierteStimmen>> result = new ArrayList<>(super.getColumnEntriesSorted());

    boolean sitzberechnungsalgorithmusVergibtSitze = isSitzberechnungsalgorithmusVergibtSitze();

    // Reihenfolge Stimmen/Rang/Stimmzettelposition, cf. KandidaturGewaehltColumnBuilder#getColumnEntriesSorted, DirektkandidaturKumulierteStimmenColumnBuilder#getColumnEntriesSorted!
    if (isWahlMitDirektwahlgebietenSelected()) {
      result.add(kandidaturKumulierteStimmenAnzahlDirektstimmenColumn);

      if (sitzberechnungsalgorithmusVergibtSitze) {
        result.add(kandidaturKumulierteStimmenGewaehltRangDirektstimmenColumn);
      }
    }

    if (isWahlMitListenwahlgebietenSelected()) {
      result.add(kandidaturKumulierteStimmenAnzahlListenstimmenColumn);

      if (isStimmzettelNurEinzelnerWahlvorschlagUnveraendertRelevant(getSelectedErgebnis())) {
        result.add(kandidaturKumulierteStimmenAnzahlListenstimmenAnteilAusEinzelstimmvergabeColumn);
        result.add(kandidaturKumulierteStimmenAnzahlListenstimmenAnteilAusWahlvorschlagstimmvergabeColumn);
      }

      if (sitzberechnungsalgorithmusVergibtSitze) {
        result.add(kandidaturKumulierteStimmenGewaehltRangListenstimmenColumn);
      }
    }

    if (isWahlMitGesamtstimmenauswertungSelected()) {
      result.add(kandidaturKumulierteStimmenAnzahlGesamtstimmenColumn);

      if (sitzberechnungsalgorithmusVergibtSitze) {
        result.add(kandidaturKumulierteStimmenGewaehltRangGesamtstimmenColumn);
      }
    }

    result.add(kandidaturKumulierteStimmenStimmzettelPositionColumn);

    return result;
  }

  private boolean isStimmzettelNurEinzelnerWahlvorschlagUnveraendertRelevant(Ergebnis ergebnis) {
    return ergebnis != null
        && listenwahlStimmeingabeKonfiguration.isStimmzetteleingabeGruppeStimmenNurEinzelnerWahlvorschlagUnveraendertRelevant(wahlParameterLoader, ergebnis.getWahl(), ergebnis.getErgebnisart());
  }
}
