/**
 * $Id$
 * $Revision$
 * $Author$
 * $Date$
 *
 * This file is part of The iWear Framework.
 * In particular this file is part of the Framework Core Library
 *
 * The iWear Framework is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by the
 * Free Software Foundation as in version 2 of the License.

 * 
 * The iWear Framework is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * The iWear Framework; if not, write to the Free Software Foundation, Inc., 59
 * Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#ifndef __MENUNODESUBMENU_H
#define __MENUNODESUBMENU_H

// Standard includes
#include <string>
#include <iostream>
#include <list>

// iWear includes
#include <iwear_uiservices/menunode.h>

namespace iwear {
namespace uiservices {

/**
 * This class represents a submenu
 * @author Carsten Rachuy
 */
class MenuNodeSubMenu : public MenuNode {

 public:
    
    /**
     * Constructor
     * @param the if of the element
     * @param parent The pointer to the parent menu node.
     * @param button_name The name of the button
     * @param button_description The description of the button
     * @param default_representation The representation of the button
     */
    MenuNodeSubMenu(const uint32_t id,
		    const string& name, 
		    const string& description,
		    const string& default_representation);
    
    /**
     * Destructor
     */
    virtual ~MenuNodeSubMenu(void);
    
    /**
     * @return the type
     */
    inline MENU_NODE_TYPE get_type(void){
	ThreadLocker tl(Mutex);
	return MENU_NODE_TYPE_SUB_MENU;
    }

    /**
     * @return The selected element or NULL if we dont have it
     * @todo Think about exceptions here
     */
    inline MenuNode* get_selected_element(void){
	if (this->selected_element == this->children.end()){
	    return NULL;
	} else {
	    return dynamic_cast<MenuNode*>(*(this->selected_element));
	}
    }

    /**
     * @param The element which should be selected
     * @todo Some consistency-checking has to be done
     */
    inline void set_selected_element(MenuNode* selected_element){
    	if(selected_element == NULL)
    	{
	    d_err << ANSI_RED << __FFL__ << "\n\t"
		  << ANSI_NORMAL  
		  << "Received NULL instead of MenuNode-Pointer" << endl;
    	}
	// Have to check whether it available
	//this->selected_element = selected_element;
	d_nons << ANSI_RED
	       << "MenuNodeSubMenu::set_selected_element() - No functionality!"
	       << ANSI_NORMAL
	       << endl;
    }


    // -------------- Adding & Removing --------------
    
    /**
     * Adds a child to the list of elements
     * @todo CONSISTENCY-CHECKING
     */
    void add_child(MenuNode* child);

    /**
     * Removes a child
     * This function only removes the child from the internal
     * list of children. The object is NOT destroyed, this has to be
     * done in the main menu class. The purpose for this is to keep
     * the destruction and deregistering (main map id --> element) in
     * the same class (Menu). 
     */
    void remove_child(MenuNode* child);



    // -------------- Moving --------------


    /**
     * @return A MenuNode* to the element left of the currently
     *         selected element.
     */
    MenuNode* go_left(void);
    
    /**
     * @return A MenuNode* to the element right of the currently
     *         selected element.
     */
    MenuNode* go_right(void);

    // ----------- Clone -----------

    /**
     * Creates a reduced copy of the node
     */
    ExportableMenuNode* export_node(void);
    

 private:
    
    /**
     * Current selected element as an iterator
     */
    list<MenuNode*>::iterator selected_element;

    /**
     * List of all children
     */
    list<MenuNode*> children;

    /**
     * @return A boolean indicating whether a child is already
     *         in the list
     */
    bool have_child(MenuNode* child);


};
 

} // namespace uiservices
} // namespace iwear


#endif // __MENUNODESUBMENU_H
