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

import static org.apache.commons.lang3.StringUtils.trimToEmpty;

import java.util.List;

import javax.enterprise.context.RequestScoped;

import org.primefaces.model.menu.DefaultMenuItem;
import org.primefaces.model.menu.DefaultMenuModel;
import org.primefaces.model.menu.DefaultSubMenu;
import org.primefaces.model.menu.MenuElement;
import org.primefaces.model.menu.MenuModel;
import org.primefaces.model.menu.Separator;

import de.ivu.elect.util.ClassUtil;

@RequestScoped
public abstract class AbstractMenuModelBuilder implements MenuEntry, MenuBuilder {

  private static final long serialVersionUID = 1L;

  private MenuModel menuModel;

  private MenuModel menuModelDisabled;

  public AbstractMenuModelBuilder() {
    super();
  }

  protected abstract List<MenuEntry> getMenuEntriesSorted();

  @Override
  public List<MenuEntry> listMenuEntries() {
    return getMenuEntriesSorted();
  }

  public MenuModel getMenuModel() {
    if (!isRendered()) {
      return null;
    }

    if (menuModel == null) {
      menuModel = buildMenuModel();
    }

    return menuModel;
  }

  public MenuModel getMenuModelDisabled() {
    if (!isRendered()) {
      return null;
    }

    if (menuModelDisabled == null) {
      menuModelDisabled = buildMenuModelDisabled();
    }

    return menuModelDisabled;
  }

  protected MenuModel buildMenuModel() {
    return buildMenuModel(false);
  }

  protected MenuModel buildMenuModelDisabled() {
    return buildMenuModel(true);
  }

  protected MenuModel buildMenuModel(boolean disabled) {
    menuModel = new DefaultMenuModel();

    if (!isRendered()) {
      return menuModel;
    }

    for (MenuEntry menuEntry : getMenuEntriesSorted()) {
      MenuElement menuElement = menuEntry.buildComponent();

      // NOTE, dass dieser Pseudo-Style erwartet wird, um einen Menüeintrag typsicher per CSS-Rule oder XPath finden zu können!
      String pseudoStyleClass = ClassUtil.getClassSimpleName(menuEntry);

      if (menuElement instanceof DefaultSubMenu) {
        DefaultSubMenu defaultSubMenu = (DefaultSubMenu) menuElement;
        defaultSubMenu.setStyleClass(trimToEmpty(defaultSubMenu.getStyleClass()) + " " + pseudoStyleClass);

        menuModel.addElement(defaultSubMenu);
      } else if (menuElement instanceof DefaultMenuItem) {
        DefaultMenuItem defaultMenuItem = (DefaultMenuItem) menuElement;

        if (disabled) {
          defaultMenuItem.setDisabled(true);
        }

        String styleClass = trimToEmpty(defaultMenuItem.getStyleClass());

        if (!styleClass.contains(pseudoStyleClass)) {
          defaultMenuItem.setStyleClass(styleClass + " " + pseudoStyleClass);
        }

        menuModel.addElement(defaultMenuItem);
      } else if (menuElement instanceof Separator) {
        menuModel.addElement(menuElement);
      } else {
        throw new IllegalStateException("Unbekannte MenuElement-Implementierung " + menuElement + ", " + menuElement.getClass());
      }
    }

    return menuModel;
  }

  @Override
  public boolean isRendered() {
    return getMenuEntriesSorted().stream().anyMatch(MenuEntry::isRendered);
  }

  @Override
  public String getLabelKey() {
    throw new UnsupportedOperationException();
  }

  @Override
  public MenuElement buildComponent() {
    throw new UnsupportedOperationException();
  }

  @Override
  public boolean isTopicActive() {
    return false;
  }
}
