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

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

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

import org.apache.deltaspike.core.api.scope.ConversationGroup;

import de.ivu.elect.business.ergebnis.control.StimmenPoolExtendedDAOFactory;
import de.ivu.elect.business.gebietsbaum.boundary.GebietSessionSelect;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.gruppe.entity.GruppeArt;
import de.ivu.elect.business.gruppeimgebiet.boundary.AbstractGruppeImGebietSearchParameters;
import de.ivu.elect.business.gruppeimgebiet.boundary.GruppeImGebietExtendedDAO;
import de.ivu.elect.business.gruppeimgebiet.boundary.GruppeImGebietSearchParameters;
import de.ivu.elect.business.gruppeimgebiet.control.GruppeImGebietReihenfolgeVorsortierer;
import de.ivu.elect.business.gruppeimgebiet.entity.GruppeImGebiet;
import de.ivu.elect.business.kandidatur.control.StimmzettelFormatter;
import de.ivu.elect.business.stimmzettel.boundary.EntityAufStimmzettelDatenStimmzettelPositionBerechnung;
import de.ivu.elect.business.stimmzettel.boundary.EntityAufStimmzettelDatenVorgeladenFactory;
import de.ivu.elect.business.stimmzettel.boundary.StimmzettelGebietErmittler;
import de.ivu.elect.business.stimmzettel.entity.EntityAufStimmzettelDaten;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.business.wahl.entity.WahlParameterExtendedLoader;
import de.ivu.elect.business.wahlvorschlag.entity.Wahlvorschlag;
import de.ivu.elect.jee.presentation.dynamictable.AbstractColumnBuilder;
import de.ivu.elect.jee.presentation.dynamictable.ColumnEntry;
import de.ivu.elect.presentation.pruefung.ZulassungPrueferRequestScope;
import de.ivu.elect.presentation.table.AbstractColumnEntry;
import de.ivu.elect.presentation.wahl.CurrentWahlZulassungspruefungExtended;
import de.ivu.elect.presentation.wahlvorschlag.WahlvorschlagRequestCache;

@Named(GruppeImGebietColumnBuilder.COMPONENT_NAME)
public class GruppeImGebietColumnBuilder extends AbstractColumnBuilder<GruppeImGebiet> {

  private static final long serialVersionUID = 1L;

  public static final String COMPONENT_NAME = "gruppeImGebietColumnBuilder";

  @Inject
  private transient GruppeImGebietExtendedDAO gruppeImGebietDao;

  @Inject
  private transient GebietSessionSelect gebietSelect;

  @Inject
  @ConversationGroup(AbstractGruppeImGebietSearchParameters.class)
  private transient GruppeImGebietSearchParameters searchParameters;

  @Inject
  private transient WahlvorschlagRequestCache wahlvorschlagRequestCache;

  @Inject
  private transient ZulassungPrueferRequestScope zulassungPrueferRequestScope;

  @Inject
  private transient EntityAufStimmzettelDatenStimmzettelPositionBerechnung entityAufStimmzettelDatenStimmzettelPositionBerechnung;

  @Inject
  private transient StimmenPoolExtendedDAOFactory stimmenPoolExtendedDAOFactory;

  @Inject
  private transient GruppeImGebietReihenfolgeVorsortierer gruppeImGebietReihenfolgeVorsortierer;

  @Inject
  private transient WahlParameterExtendedLoader wahlParameterExtendedLoader;

  @Inject
  private transient StimmzettelFormatter stimmzettelFormatter;

  @Inject
  private transient StimmzettelGebietErmittler stimmzettelGebietErmittler;

  @Inject
  private transient CurrentWahlZulassungspruefungExtended currentWahlZulassungspruefung;

  protected AbstractColumnEntry<GruppeImGebiet> gruppeImGebietPositionFortlaufendColumn;

  protected AbstractColumnEntry<GruppeImGebiet> gruppeImGebietPositionFixiertColumn;

  protected AbstractColumnEntry<GruppeImGebiet> gruppeImGebietGruppeSchluesselColumn;

  protected AbstractColumnEntry<GruppeImGebiet> gruppeImGebietWahlvorschlagKennwortColumn;

  protected AbstractColumnEntry<GruppeImGebiet> gruppeImGebietDirektkandidatVorhandenColumn;

  protected AbstractColumnEntry<GruppeImGebiet> gruppeImGebietDirektkandidatZulassungColumn;

  protected AbstractColumnEntry<GruppeImGebiet> gruppeImGebietListeVorhandenColumn;

  protected AbstractColumnEntry<GruppeImGebiet> gruppeImGebietListeZulassungColumn;

  protected AbstractColumnEntry<GruppeImGebiet> gruppeImGebietStimmzettelPositionColumn;

  private Boolean wahlMitDirektkandidatengebieten;

  private Boolean wahlMitListengebieten;

  private EntityAufStimmzettelDaten entityAufStimmzettelDaten;

  public GruppeImGebietColumnBuilder() {
    super();
  }

  @Override
  protected void initColumns() {
    gruppeImGebietPositionFortlaufendColumn = new GruppeImGebietPositionFortlaufendColumn(getMessages());
    gruppeImGebietPositionFixiertColumn = new GruppeImGebietFixiertColumn(getMessages(), getIcons());

    gruppeImGebietGruppeSchluesselColumn = new GruppeImGebietGruppeSchluesselColumn(getMessages());

    gruppeImGebietWahlvorschlagKennwortColumn = new GruppeImGebietWahlvorschlagKennwortColumn(getMessages());

    if (isWahlMitDirektkandidatengebietenSelected()) {
      gruppeImGebietDirektkandidatVorhandenColumn = new GruppeImGebietDirektkandidatVorhandenColumn(getMessages(), getEntityAufStimmzettelDaten());
      gruppeImGebietDirektkandidatZulassungColumn = new GruppeImGebietDirektkandidatZulassungColumn(getMessages(), getSelectedGebiet(), getEntityAufStimmzettelDaten(),
          getCurrentWahlZulassungspruefung());
    }

    if (isStimmzettelPositionEinblenden()) {
      gruppeImGebietStimmzettelPositionColumn = new GruppeImGebietStimmzettelPositionColumn(getMessages(), getIcons(), getSelectedGebiet(), getEntityAufStimmzettelDaten());
    }

    if (isWahlMitListengebietenSelected()) {
      gruppeImGebietListeVorhandenColumn = new GruppeImGebietListeVorhandenColumn(getMessages(), getEntityAufStimmzettelDaten());
      gruppeImGebietListeZulassungColumn = new GruppeImGebietListeZulassungColumn(getMessages(), getSelectedGebiet(), getEntityAufStimmzettelDaten(), getCurrentWahlZulassungspruefung());
    }
  }

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

    result.add(gruppeImGebietPositionFortlaufendColumn);

    if (isStimmzettelPositionEinblenden()) {
      result.add(gruppeImGebietStimmzettelPositionColumn);
    }

    if (mindEineGruppeImGebietHatFixiertePosition()) {
      result.add(gruppeImGebietPositionFixiertColumn);
    }

    result.add(gruppeImGebietGruppeSchluesselColumn);

    result.add(gruppeImGebietWahlvorschlagKennwortColumn);

    if (isWahlMitListengebietenSelected()) {
      if (getSelectedGebiet().isListenwahlgebietOderDrunter()
          && getCurrentWahlZulassungspruefung().isZulassungBearbeitbar()) { // WASDE-1356
        result.add(gruppeImGebietListeZulassungColumn);
      } else {
        result.add(gruppeImGebietListeVorhandenColumn);
      }
    }

    if (isWahlMitDirektkandidatengebietenSelected()) {
      if (getSelectedGebiet().isDirektwahlgebietOderDrunter()
          && getCurrentWahlZulassungspruefung().isZulassungBearbeitbar()) { // WASDE-1356
        result.add(gruppeImGebietDirektkandidatZulassungColumn);
      } else {
        result.add(gruppeImGebietDirektkandidatVorhandenColumn);
      }
    }

    return result;
  }

  private boolean isStimmzettelPositionEinblenden() {
    return stimmzettelGebietErmittler.isStimmzettelGebietOderDarunter(gebietSelect.getEntity(), wahlvorschlagRequestCache::getAlleWahlvorschlaege);
  }

  protected boolean isWahlMitDirektkandidatengebietenSelected() {
    if (wahlMitDirektkandidatengebieten == null) {
      wahlMitDirektkandidatengebieten = isWahlSelected() && getSelectedWahl().isWahlMitDirektkandidatengebieten();
    }

    return wahlMitDirektkandidatengebieten;
  }

  protected boolean isWahlMitListengebietenSelected() {
    if (wahlMitListengebieten == null) {
      wahlMitListengebieten = isWahlSelected() && getSelectedWahl().isWahlMitListengebieten();
    }

    return wahlMitListengebieten;
  }

  private boolean mindEineGruppeImGebietHatFixiertePosition() {
    if (!isGebietSelected()) {
      return false;
    }

    return gruppeImGebietDao.findByCountGruppeImGebietByGebietAndUngleichGruppeArtAndPositionFixiert(getSelectedGebiet(), GruppeArt.SYSTEM_GRUPPE) > 0L;
  }

  protected boolean isWahlSelected() {
    return isGebietSelected() && getSelectedGebiet().getWahl() != null;
  }

  protected Wahl getSelectedWahl() {
    return getSelectedGebiet().getWahl();
  }

  protected boolean isGebietSelected() {
    return gebietSelect.isSelected();
  }

  protected Gebiet getSelectedGebiet() {
    return gebietSelect.getEntity();
  }

  protected EntityAufStimmzettelDaten getEntityAufStimmzettelDaten() {
    if (entityAufStimmzettelDaten == null) {
      List<Wahlvorschlag> wahlvorschlaegeInWahl = wahlvorschlagRequestCache.getAlleWahlvorschlaege();

      entityAufStimmzettelDaten = new EntityAufStimmzettelDatenVorgeladenFactory(wahlParameterExtendedLoader, zulassungPrueferRequestScope.getZulassungPruefer(), stimmzettelFormatter,
          entityAufStimmzettelDatenStimmzettelPositionBerechnung, stimmenPoolExtendedDAOFactory, gruppeImGebietReihenfolgeVorsortierer, wahlvorschlaegeInWahl).getEntityAufStimmzettelDaten();
    }

    return entityAufStimmzettelDaten;
  }

  protected CurrentWahlZulassungspruefungExtended getCurrentWahlZulassungspruefung() {
    return currentWahlZulassungspruefung;
  }
}
