/**
 * $Id$
 * $Revision$
 * $Author$
 * $Date$
 *
 * This file is part of The iWear Framework.
 * In particular this file is part of the uiservices 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 __MENUNODE_H
#define __MENUNODE_H

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

// iWear includes
#include <iwear/threadlocked.h>
#include <iwear/debugstream.h>
#include <iwear/utility.h>

using namespace std;

namespace iwear {
namespace uiservices {


// Little enum for the node types
enum MENU_NODE_TYPE{
    MENU_NODE_TYPE_SIMPLE_BUTTON,
    MENU_NODE_TYPE_JUMP_BUTTON,
    MENU_NODE_TYPE_QUIT_BUTTON,
    MENU_NODE_TYPE_SUB_MENU,
    MENU_NODE_TYPE_SWITCH_BUTTON,
    MENU_NODE_TYPE_UP_BUTTON,
    num_MENU_NODE_TYPE
};
 
// Forward decleration of class ExportableMenuNode
 class ExportableMenuNode;


/**
 * This class represents the base class for all nodes and is used by
 * the menu class.
 * @author Carsten Rachuy
 */
class MenuNode : public ThreadLocked {
    

 public:
    
    /**
     * Constructor
     * @param id the id of the id of the element
     * @param parent The pointer to the parent button.
     * @param button_name The name of the button
     * @param button_description The description of the button
     * @param default_representation The representation of the button
     */
    MenuNode(const uint32_t id,
	     const string&  name, 
	     const string&  description,
	     const string&  default_representation);

    /**
     * Destructor
     */
    virtual ~MenuNode(void);

    /**
     * @return the type
     */
    virtual MENU_NODE_TYPE get_type(void) = 0;

    // ----------- Getter -----------

    /**
     * @return the id
     */
    inline virtual uint32_t get_id(void){
	ThreadLocker tl(Mutex);
	return this->id;
    }
    
    /**
     * @return The name
     */
    inline virtual string& get_name(void){
	ThreadLocker tl(Mutex);
	return this->name;
    }

    /**
     * @return The description
     */
    inline virtual string& get_description(void){
	ThreadLocker tl(Mutex);
	return this->description;
    }

    /**
     * @return The representation
     */
    inline virtual string& get_default_representation(void){
	ThreadLocker tl(Mutex);
	return this->default_representation;
    }

    /**
     * @return A bool indicating whether the button is active
     */
    inline virtual bool is_active(void){
	ThreadLocker tl(Mutex);
	return this->active;
    }
    
    /**
     * @return the parent
     */
    inline virtual MenuNode* get_parent(void){
	ThreadLocker tl(Mutex);
	return this->parent;
    }

    // ----------- Setter -----------

    /**
     * @param The new name
     */
    inline virtual void set_name(const string& name){
	ThreadLocker tl(Mutex);
	this->name = name;
    }

    /**
     * @param The new description
     */
    inline virtual void set_description(const string& description){
	ThreadLocker tl(Mutex);
	this->description = description;
    }

    /**
     * @param The new representation
     */
    inline virtual void set_default_representation(const string& default_representation){
	ThreadLocker tl(Mutex);
	this->default_representation = default_representation;
    }

    /**
     * @param A boolean which indicates the active-state of the button
     */
    inline virtual void set_active(bool active){
	ThreadLocker tl(Mutex);
	this->active = active;
    }
        
    
    /**
     * Set the parent
     */
    inline virtual void set_parent(MenuNode* parent){
	ThreadLocker tl(Mutex);
	if (this->parent == NULL){
	    /*
	    d_nons << ANSI_BLUE 
		   << "MenuNode <" 
		   << ANSI_YELLOW
		   << this->name  
		   << ANSI_BLUE
		   << "> set <" 
		   << ANSI_YELLOW
		   << parent->get_name() 
		   << ANSI_BLUE
		   << "> as parent." 
		   << ANSI_NORMAL 
		   << endl;
	    */
	    this->parent = parent;
	} else {
	    d_nons << ANSI_RED
		   << "MenuNode <" 
		   << ANSI_YELLOW
		   << this->name 
		   << ANSI_RED
		   << "> was requested to set <" 
		   << ANSI_YELLOW
		   << parent->get_name()
		   << ANSI_RED
		   << "> as parent. Parent already set earlyer, ignoring request!" 
		   << ANSI_NORMAL 
		   << endl;	    
	}
    }

    
    // ----------- Other -----------
    

    /**
     * Equality
     * @param menu_node The MenuNode which should be compared
     *        to the actual one
     */
    inline bool operator==(MenuNode& menu_node){
	ThreadLocker tl(Mutex);
        return ( this->id == menu_node.get_id() );
    }

    
    /**
     * Inequality
     * @param menu_node The MenuNode which should be compared
     *        to the actual one     */
    inline bool operator!=(MenuNode& menu_node){
	ThreadLocker tl(Mutex);
        return !(*this == menu_node);
    }

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

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


 protected:

    /**
     * The id of the node
     */
    uint32_t id;

    /**
     * The name of the node
     */
    string name;
    
    /**
     * The description of the node
     */
    string description;

    /**
     * The default representation of the node
     */
    string default_representation;

    /**
     * Is the node active or not
     */
    bool active;

    /**
     * The parent
     */
    MenuNode* parent;

};
 

} // namespace uiservices
} // namespace iwear


#endif // __MENUNODE_H

