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

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;

import javax.annotation.Nonnull;
import javax.inject.Inject;
import javax.inject.Named;

import de.ivu.elect.presentation.ergebnis.AbstractCoreSitzeSearchView;
import org.apache.deltaspike.core.api.scope.ConversationGroup;

import de.ivu.elect.business.ergebnis.boundary.AbstractSitzeSearchParameters;
import de.ivu.elect.business.ergebnis.boundary.SitzeExtendedDAO;
import de.ivu.elect.business.ergebnis.boundary.SitzeSearchParameters;
import de.ivu.elect.business.ergebnis.entity.Ergebnis;
import de.ivu.elect.business.ergebnis.entity.Sitze;
import de.ivu.elect.business.ergebnis.entity.SitzeZusammengefasst;
import de.ivu.elect.business.gebietsbaum.boundary.GebietExtendedDAO;
import de.ivu.elect.business.gruppe.boundary.GruppeExtendedDAO;
import de.ivu.elect.business.wahl.boundary.WahlSessionSelector;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.jee.presentation.dynamictable.AbstractColumnBuilder;
import de.ivu.elect.jee.presentation.dynamictable.ColumnEntry;
import de.ivu.elect.jee.presentation.dynamictable.ColumnType;
import de.ivu.elect.presentation.table.DefaultColumnEntry;

@Named(SitzeColumnBuilder.COMPONENT_NAME)
public class SitzeColumnBuilder extends AbstractColumnBuilder<Sitze> {

  private static final long serialVersionUID = 1L;

  public static final String COMPONENT_NAME = "sitzeColumnBuilder";

  @Inject
  private transient SitzeExtendedDAO sitzeExtendedDAO;

  @Inject
  private transient GebietExtendedDAO gebietExtendedDAO;

  @Inject
  private transient GruppeExtendedDAO gruppeExtendedDAO;

  @Inject
  private transient WahlSessionSelector wahlSessionSelector;

  @Inject
  @ConversationGroup(AbstractSitzeSearchParameters.class)
  private transient SitzeSearchParameters searchParameters;

  protected SitzeGruppeNameKennwortColumn sitzeGruppeNameKennwortColumn;

  protected SitzeGruppeKurznameColumn sitzeGruppeKurznameColumn;

  protected SitzeGruppeFarbeColumn sitzeGruppeFarbeColumn;

  protected AbstractSitzeColumn<Sitze> sitzeAnzahlColumn;

  protected AbstractSitzeColumn<Sitze> sitzeAnzahlAnspruchColumn;

  protected DefaultColumnEntry<Sitze> sitzeAnzahlVorperiodeColumn;

  protected DefaultColumnEntry<Sitze> sitzeAnzahlAnspruchVorperiodeColumn;

  public SitzeColumnBuilder() {
    super();
  }

  @Override
  public void initColumns() {
    sitzeGruppeNameKennwortColumn = new SitzeGruppeNameKennwortColumn(getMessages(), getSelectedWahl());
    sitzeGruppeKurznameColumn = new SitzeGruppeKurznameColumn(getMessages());
    sitzeGruppeFarbeColumn = new SitzeGruppeFarbeColumn(getMessages());

    sitzeAnzahlColumn = AbstractSitzeColumn.createSitzeAnzahlColumn(getMessages());
    sitzeAnzahlAnspruchColumn = AbstractSitzeColumn.createSitzeAnzahlAnspruchColumn(getMessages());

    sitzeAnzahlVorperiodeColumn = new DefaultColumnEntry<>("scb-savc", getMessages(), "sitze.column.builder.anzahl.vorperiode", ColumnType.LONG, e -> getAnzahlFromSitze(e, Sitze::getAnzahl));
    sitzeAnzahlAnspruchVorperiodeColumn = new DefaultColumnEntry<>("scb-saavc", getMessages(), "sitze.column.builder.anspruch.vorperiode", ColumnType.LONG,
        e -> getAnzahlFromSitze(e, Sitze::getAnzahlAnspruch));
  }

  @Nonnull
  private Long getAnzahlFromSitze(Sitze e, Function<Sitze, Long> fct) {
    if (!AbstractCoreSitzeSearchView.PSEUDO_GRUPPE_SCHLUESSEL_SUMME.equals(e.getGruppe().getSchluessel())) {
      if (e instanceof SitzeZusammengefasst) {
        e.setGebiet(gebietExtendedDAO.attach(e.getGebiet()));
        e.setGruppe(gruppeExtendedDAO.attach(e.getGruppe()));
      } else {
        e = sitzeExtendedDAO.attach(e);
      }
    }

    return Optional.ofNullable(e.getSitzeVorperiode(getSelectedWahl(), sitzeExtendedDAO)).map(fct).orElse(0L);
  }

  @Override
  protected List<ColumnEntry< ? super Sitze>> getColumnEntriesSorted() {
    List<ColumnEntry< ? super Sitze>> result = new ArrayList<>();

    result.add(sitzeGruppeFarbeColumn);
    result.add(sitzeGruppeNameKennwortColumn);
    result.add(sitzeGruppeKurznameColumn);

    result.add(sitzeAnzahlColumn);
    result.add(sitzeAnzahlAnspruchColumn);

    Ergebnis ergebnis = searchParameters.getErgebnis();

    if (ergebnis == null || !ergebnis.getErgebnisart().isVorperiode()) {
      result.add(sitzeAnzahlVorperiodeColumn);
      result.add(sitzeAnzahlAnspruchVorperiodeColumn);
    }

    return result;
  }

  public AbstractSitzeColumn<Sitze> getSitzeAnzahlColumn() {
    return sitzeAnzahlColumn;
  }

  public SitzeGruppeNameKennwortColumn getSitzeGruppeNameOrEinzelbewerberKennwortColumn() {
    return sitzeGruppeNameKennwortColumn;
  }

  public SitzeGruppeFarbeColumn getSitzeGruppeFarbeColumn() {
    return sitzeGruppeFarbeColumn;
  }

  public SitzeGruppeKurznameColumn getSitzeGruppeKurznameColumn() {
    return sitzeGruppeKurznameColumn;
  }

  private Wahl getSelectedWahl() {
    return wahlSessionSelector.getEntity();
  }
}
