package examples.forms;

import java.util.ArrayList;

import net.sourceforge.tapestry_jsmenu.api.BasicJSCookMenuItem;
import net.sourceforge.tapestry_jsmenu.api.IJSCookMenuItem;
import net.sourceforge.tapestry_jsmenu.api.IMenuItemRenderer;
import org.apache.tapestry.IComponent;
import org.apache.tapestry.IRequestCycle;
import org.apache.tapestry.annotations.InjectComponent;
import org.apache.tapestry.annotations.Persist;
import org.apache.tapestry.event.PageBeginRenderListener;
import org.apache.tapestry.event.PageEvent;
import org.apache.tapestry.html.BasePage;

public abstract class Forms extends BasePage implements PageBeginRenderListener{

  /*
   * inject the renderer components to be used in the itemRenderer.render method
   */
  @InjectComponent("normalLink")
  public abstract IComponent getNormalLink();  
  @InjectComponent("login")
  public abstract IComponent getLogin();
  
  /**
   * there are three types of items
   */
  public enum ItemType {
    TYPE_LOGIN_FORM, TYPE_ALWAYS, TYPE_SHOW_WHEN_LOGGED_IN;
  }
  
  @Persist("client")
  public abstract String getUser();
  
  @Persist("client")
  public abstract String getPassword();
  
  @Persist("session")
  public abstract boolean isLoggedIn();
  public abstract void setLoggedIn(boolean loggedIn);
  
  /**
   * construct a IMenuItemRenderer instance that is used to choose the 
   * renderer component for a given item
   * In this example the items value 
   * is an Array of the items name (String) and the type (ItemType)
   * See the contruction of the model in the pageBeginRender method 
   */
  private IMenuItemRenderer itemRenderer = new IMenuItemRenderer(){
    public IComponent render(IJSCookMenuItem item) {
      Object[] value = (Object[])((BasicJSCookMenuItem)item).getValue();
      ItemType type = (ItemType)(value[1]);
      switch(type){   
      // Note : return null will exclude the item with all its sub menues from the displayed menu
        case TYPE_LOGIN_FORM           : return isLoggedIn() null : getLogin();
        case TYPE_ALWAYS         : return getNormalLink();
        case TYPE_SHOW_WHEN_LOGGED_IN  : return isLoggedIn() ? getNormalLink() null;
        default              return null;
        }
    }
  };

  /**
   * The 'itemRenderer' field is bound to the 'contentRenderer' parameter of the 
   * menu component. 
   */
  public IMenuItemRenderer getItemRenderer(){
    return itemRenderer ;
  }
  
  /**
   * The 'menuItem' property referenced in the bindings. It holds the current
   * rendered item of the model 
   */
  public abstract IJSCookMenuItem getMenuItem();
  
  
    private ArrayList<IJSCookMenuItem> model = null;
  
  /**
   * The menu model provided by the java code 
   * must be an instance of Iterable<IJSCookMenuItem>
   */
  public Iterable<IJSCookMenuItem> getMenuModel(){
    return model;
  }

  /**
   * construct a model when the page instance is new
   */
  public void pageBeginRender(PageEvent arg0) {
    if(model == null){ 
      model = new ArrayList<IJSCookMenuItem>();
      //add login form item
      BasicJSCookMenuItem logInItem = 
        new BasicJSCookMenuItem(new Object[]{null, ItemType.TYPE_LOGIN_FORM});
      model.add(logInItem);
      
      model.add(IJSCookMenuItem.MENU_SEPARATOR);
      
      
      //add some items that display only when user is logged in
      model.add(new BasicJSCookMenuItem(new Object[]{"Log out"
          ItemType.TYPE_SHOW_WHEN_LOGGED_IN}));
      model.add(IJSCookMenuItem.MENU_SEPARATOR);
      //email with submenu
      BasicJSCookMenuItem email = 
        new BasicJSCookMenuItem(new Object[]{"My Email"
            ItemType.TYPE_SHOW_WHEN_LOGGED_IN});
      model.add(email);
      email.addItem(new BasicJSCookMenuItem(new Object[]{"Send new Mail"
          ItemType.TYPE_SHOW_WHEN_LOGGED_IN}));
      email.addItem(new BasicJSCookMenuItem(new Object[]{"See incoming mails"
          ItemType.TYPE_SHOW_WHEN_LOGGED_IN}));
      
      
      
      model.add(IJSCookMenuItem.MENU_SEPARATOR);
      
      //add some items that display always
      model.add(new BasicJSCookMenuItem(new Object[]{"Community"
          ItemType.TYPE_ALWAYS}));
      model.add(new BasicJSCookMenuItem(new Object[]{"News"
          ItemType.TYPE_ALWAYS}));
      model.add(new BasicJSCookMenuItem(new Object[]{"Contact"
          ItemType.TYPE_ALWAYS}));
    }  
  }
  
  /**
   * This is called when one of the menu items is clicked
   */
  public void onNavigate(IRequestCycle cycle, String value){
    if(value.equals("Log out")) {
      setLoggedIn(false);
    }
    else {
      System.out.println("navigating from menuitem " + value );
    }
  }
   
  /**
   * This is called when the user logs in
   */
  public void onLogin(IRequestCycle cycle){
    setLoggedIn(true);
  }
  
  
}