
package de.ivu.elect.presentation.wahl.menu;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import javax.inject.Inject;

import de.ivu.elect.business.security.control.ElectCommonPrincipal;
import de.ivu.elect.business.wahl.boundary.WahlterminExtendedDAO;
import de.ivu.elect.business.wahl.boundary.WahlterminSessionSelect;
import de.ivu.elect.business.wahl.control.WahlterminByWahldatumComparator;
import de.ivu.elect.business.wahl.entity.Wahltermin;
import de.ivu.elect.business.wahl.entity.WahlterminConstants;
import de.ivu.elect.jee.presentation.menu.AbstractSubMenuEntry;
import de.ivu.elect.jee.presentation.menu.MenuEntry;
import de.ivu.elect.presentation.dashboard.menu.DashboardMenuItemEntry;
import de.ivu.elect.presentation.dokumente.menu.DokumentVorlageVerwaltenMenuItemEntry;
import de.ivu.elect.presentation.email.menu.EmailVorlageVerwaltenMenuItemEntry;
import de.ivu.elect.presentation.protokollierung.menu.LoeschProtokollMenuItemEntry;
import de.ivu.elect.presentation.staat.menu.StaatenGruppeVerwaltenMenuItemEntry;
import de.ivu.elect.presentation.wahl.action.WahlterminZurBearbeitungAuswaehlenAction;
import de.ivu.elect.presentation.wahl.menu.dynamic.AbstractWahlterminSelectMenuItemEntry;


import static java.util.Collections.emptyList;

public class WahlterminMainMenuEntry extends AbstractSubMenuEntry {

  private static final long serialVersionUID = 1L;

  @Inject
  private transient DashboardMenuItemEntry dashboardMenuItemEntry;

  @Inject
  private transient WahlterminSessionSelect wahlterminSelect;

  @Inject
  private transient WahlterminExtendedDAO wahlterminExtendedDAO;

  @Inject
  private transient WahlterminEditMenuItemEntry wahlterminEditMenuItemEntry;

  @Inject
  private transient WahlterminSearchMenuItemEntry wahlterminSearchMenuItemEntry;

  @Inject
  protected transient WahlterminCreateMenuItemEntry wahlterminCreateMenuItemEntry;

  @Inject
  protected transient WahlterminStichwahlAnlegenMenuItemEntry wahlterminStichwahlAnlegenMenuItemEntry;

  @Inject
  private transient WahlterminCopyAnlegenMenuItemEntry wahlterminCopyAnlegenMenuItemEntry;

  @Inject
  private transient WahlDokumentplatzhalterEditMenuItemEntry wahlDokumentplatzhalterEditMenuItemEntry;

  @Inject
  private transient WahlParameterSearchMenuItemEntry wahlParameterSearchMenuItemEntry;

  @Inject
  private transient WahlParameterExportMenuItemEntry wahlParameterExportMenuItemEntry;

  @Inject
  private transient WahlParameterImportMenuItemEntry wahlParameterImportMenuItemEntry;

  @Inject
  private transient DokumentVorlageVerwaltenMenuItemEntry dokumentVorlageVerwaltenMenuItemEntry;

  @Inject
  private transient EmailVorlageVerwaltenMenuItemEntry emailVorlageVerwaltenMenuItemEntry;

  @Inject
  private transient StaatenGruppeVerwaltenMenuItemEntry staatenGruppeVerwaltenMenuItemEntry;

  @Inject
  private transient AbstractWahlterminSelectMenuItemEntry.WahlterminSelect1MenuItemEntry wahlterminSelect1MenuItemEntry;

  @Inject
  private transient AbstractWahlterminSelectMenuItemEntry.WahlterminSelect2MenuItemEntry wahlterminSelect2MenuItemEntry;

  @Inject
  private transient AbstractWahlterminSelectMenuItemEntry.WahlterminSelect3MenuItemEntry wahlterminSelect3MenuItemEntry;

  @Inject
  private transient AbstractWahlterminSelectMenuItemEntry.WahlterminSelect4MenuItemEntry wahlterminSelect4MenuItemEntry;

  @Inject
  private transient AbstractWahlterminSelectMenuItemEntry.WahlterminSelect5MenuItemEntry wahlterminSelect5MenuItemEntry;

  @Inject
  private transient AbstractWahlterminSelectMenuItemEntry.WahlterminSelect6MenuItemEntry wahlterminSelect6MenuItemEntry;

  @Inject
  private transient AbstractWahlterminSelectMenuItemEntry.WahlterminSelect7MenuItemEntry wahlterminSelect7MenuItemEntry;

  @Inject
  private transient AbstractWahlterminSelectMenuItemEntry.WahlterminSelect8MenuItemEntry wahlterminSelect8MenuItemEntry;

  @Inject
  private transient AbstractWahlterminSelectMenuItemEntry.WahlterminSelect9MenuItemEntry wahlterminSelect9MenuItemEntry;

  @Inject
  private transient AbstractWahlterminSelectMenuItemEntry.WahlterminSelect10MenuItemEntry wahlterminSelect10MenuItemEntry;

  @Inject
  private transient ExterneLinks externeLinks;

  @Inject
  private transient WahlterminZurBearbeitungAuswaehlenAction wahlterminZurBearbeitungAuswaehlenAction;

  @Inject
  private transient ElectCommonPrincipal electCommonPrincipal;

  @Inject
  private transient LoeschProtokollMenuItemEntry loeschProtokollMenuItemEntry;

  public WahlterminMainMenuEntry() {
    super();
  }

  @Override
  protected List<MenuEntry> getSubMenuEntriesSorted() {
    List<MenuEntry> result = new ArrayList<>();

    result.add(dashboardMenuItemEntry);
    result.add(wahlterminEditMenuItemEntry);
    result.add(wahlterminSearchMenuItemEntry);

    addWahlterminCreate(result);

    result.add(loeschProtokollMenuItemEntry);

    result.add(separator);
    result.add(wahlParameterSearchMenuItemEntry);
    result.add(wahlParameterImportMenuItemEntry);
    result.add(wahlParameterExportMenuItemEntry);

    result.add(separator);
    addWahltermineAuswaehlen(result);

    result.add(separator);
    result.add(dokumentVorlageVerwaltenMenuItemEntry);
    result.add(wahlDokumentplatzhalterEditMenuItemEntry); // ELECTKOM-191
    result.add(emailVorlageVerwaltenMenuItemEntry);
    result.add(staatenGruppeVerwaltenMenuItemEntry);

    addAfterDokumentvorlagen(result);

    addExterneLinks(result);

    return result;
  }

  private void addExterneLinks(List<MenuEntry> result) {
    result.add(separator);
    externeLinks.addExterneLinks(result);
  }

  protected void addWahltermineAuswaehlen(List<MenuEntry> result) {
    List<Wahltermin> wahltermine = bestimmeAuszuwaehlendeWahltermine();

    for (int i = 0; i < wahltermine.size(); i++) {
      addWahlterminAuswahl(result, wahltermine.get(i), i + 1);
    }
  }

  protected void addAfterDokumentvorlagen(List<MenuEntry> result) {
    // nichts zu tun
  }

  protected void addWahlterminCreate(List<MenuEntry> result) {
    result.add(wahlterminStichwahlAnlegenMenuItemEntry); // Falls eine Stichwahl möglich ist, wird diese sicher vor einem neuen Wahltermin angelegt...

    result.add(wahlterminCreateMenuItemEntry);

    result.add(wahlterminCopyAnlegenMenuItemEntry);
  }

  @Override
  public String getLabelKey() {
    return WahlterminConstants.MESSAGE_KEY_ENTITY_MEHRZAHL;
  }

  private void addWahlterminAuswahl(List<MenuEntry> result, Wahltermin wahltermin, int count) {
    AbstractWahlterminSelectMenuItemEntry menuItemEntry;

    switch (count) {
      case 1:
        menuItemEntry = wahlterminSelect1MenuItemEntry;
        break;
      case 2:
        menuItemEntry = wahlterminSelect2MenuItemEntry;
        break;
      case 3:
        menuItemEntry = wahlterminSelect3MenuItemEntry;
        break;
      case 4:
        menuItemEntry = wahlterminSelect4MenuItemEntry;
        break;
      case 5:
        menuItemEntry = wahlterminSelect5MenuItemEntry;
        break;
      case 6:
        menuItemEntry = wahlterminSelect6MenuItemEntry;
        break;
      case 7:
        menuItemEntry = wahlterminSelect7MenuItemEntry;
        break;
      case 8:
        menuItemEntry = wahlterminSelect8MenuItemEntry;
        break;
      case 9:
        menuItemEntry = wahlterminSelect9MenuItemEntry;
        break;
      case 10:
        menuItemEntry = wahlterminSelect10MenuItemEntry;
        break;
      default:
        menuItemEntry = null;
    }

    if (menuItemEntry != null) {
      menuItemEntry.setWahltermin(wahltermin);

      result.add(menuItemEntry);
    }
  }

  private List<Wahltermin> bestimmeAuszuwaehlendeWahltermine() {
    if (electCommonPrincipal.isLoggedIn() && electCommonPrincipal.getMandant() != null) {
      Wahltermin selectedWahltermin = wahlterminSelect.getEntity();

      return wahlterminExtendedDAO.findByAll(electCommonPrincipal.getMandant()).stream() //
          .filter(wahltermin -> !wahltermin.isWahlhelferdatenbank() && !wahltermin.equals(selectedWahltermin))
          .filter(wahltermin -> wahltermin.getStatus().isCrontabErstellbar()) // nur aktive Wahlen einblenden
          .filter(wahltermin -> wahlterminZurBearbeitungAuswaehlenAction.isActionPossible(wahltermin)) // ELECT-7407
          .filter(wahltermin -> wahltermin.isRechtZumEinsehenVorhanden(electCommonPrincipal)) // ELECT-7407
          .sorted(WahlterminByWahldatumComparator.ASCENDING) //
          .collect(Collectors.toList());
    }

    return emptyList();
  }

  public void addAuszuwaehlendeWahltermineMenuEntries(List<MenuEntry> result, boolean addSeparator) {
    addWahltermineAuswaehlen(result);
  }
}
