/**
 * $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 __EXPORTABLEMENUNODE_H
#define __EXPORTABLEMENUNODE_H

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

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


using namespace std;

namespace iwear {
namespace uiservices {


/**
 * Exportable version of a whole menu which is like a copy of the whole
 * menu (including the structure).
 * @author Carsten Rachuy
 */
class ExportableMenuNode : public ThreadLocked {

 public:
    
    /**
     * Constructor
     * @param id                     The id of the element
     * @param button_name            The name of the button
     * @param button_description     The description of the button
     * @param default_representation The representation of the button
     */
    ExportableMenuNode(const uint32_t id,
		       const MENU_NODE_TYPE menu_node_type,
		       const string&  name, 
		       const string&  description,
		       const string&  default_representation,
		       const bool     active);

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

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

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

    /**
     * @return the type
     */
    virtual MENU_NODE_TYPE get_type(void){
	ThreadLocker tl(Mutex);
	return this->menu_node_type;
    }    
    
    /**
     * @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 ExportableMenuNode* get_parent(void){
	ThreadLocker tl(Mutex);
	return this->parent;
    }
    
    inline void set_parent(ExportableMenuNode* parent){
	ThreadLocker tl(Mutex);
	this->parent = parent;
    }


    /**
     * @return
     */
    inline const vector<ExportableMenuNode*>& get_children(void){
	return this->children;
    }



    /**
     * @return A pointer to the element with the given id
     */
    virtual ExportableMenuNode* get_node_with_id(uint32_t element_id){
	// Am I the node?
	if (this->id == element_id){
	    return this;
	}
	// Obviously not...
	vector<ExportableMenuNode*>::iterator it;
	for (it = children.begin(); it != children.end(); it++){
	    ExportableMenuNode* node_with_id =
		(*it)->get_node_with_id(element_id);
	    if (node_with_id != NULL){
		return node_with_id;
	    }
	}
	return NULL;
    }

    
    // ----------- Add a child -----------
    inline void add_child(ExportableMenuNode* exportable_menu_node){
	ThreadLocker tl(Mutex);
	this->children.push_back(exportable_menu_node);
	exportable_menu_node->set_parent(this);
    }


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

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

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

    /**
     * The type of the node
     */
    MENU_NODE_TYPE menu_node_type;

    /**
     * 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
     */
    ExportableMenuNode* parent;

    /**
     * Children
     */ 
    vector<ExportableMenuNode*> children;


};
 

} // namespace uiservices
} // namespace iwear


#endif // __EXPORTABLEMENUNODE_H

