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

#include <string>
#include <map>
#include <utility> // for pair used in maps
#include <stdint.h>
#include <time.h>
#include <sys/time.h>

#ifndef __CONTEXTPART_H
#include <iwear-context/contextpart.h>
#endif

#ifndef __CONTEXTENUMS_H
#include <iwear-context/contextenums.h>
#endif

using namespace std;

namespace iwear{
namespace context{

class ContextObject : public ContextPart{
	
private:
protected: 

    /**
     * The name of the context.
     */
    const string name;

    /**
     * The type of the subclass - needed for casting.
     */
    ContextType context_type;

    /**
     * The level of the object in the context-tree.
     */
    uint32_t level;
    
    /**
     * The parents of the context in the tree. This is needed evaluating the
     * composite contexts later.
     */
    map<const string, ContextObject*> parents;

    /**
     * The standard constructor ist private and should not be used.
     */
    ContextObject(void):name(""){}

    /**
     * The time when the contexts value changed last time. Also holds data of
     * the timezone.
     */
    timeval last_change;

public:
    /**
     * The constructor to be used to create instances.
     * @param name the name of the instance.
     * @param context_type the type of the context.
     * @param level how deep the node is in the context-tree. Where the leafs
     * are on level 0.
     */
    ContextObject(string name, ContextType context_type, uint32_t level=0)
	: name(name), context_type(context_type), 
	  level(level)
    {
	gettimeofday(&last_change, NULL);
    }
    
    /**
     * The destructor.
     */
    virtual ~ContextObject(void){

    }

    /**
     * Get the parents of this ContextObject.
     *
     * @return a map of the parents.
     */
    map<const string, ContextObject*>& get_parents(void){
	return parents;
    }

    /**
     * Get the name of this ContextObject.
     *
     * @return the name of this ContextObject.
     */
    const string& get_name(void) const{
	return name;
    }

    /**
     * Get the time when the contexts value changed last time.
     *
     * @return timestamp of the last change.
     */ 
    const timeval& get_last_timestamp(void) const{
	return last_change;
    }

    /**
     * Get the type of the context.
     *
     * @return the type of the context.
     */
    const ContextType get_context_type(void) const{
	return context_type;
    }

    /**
     * Get the level of the instance in the context-tree. We count beginning
     * from the leafs that are on level 0.
     *
     * @return the level of the context in the tree
     */
    uint32_t get_level(void) const{
	return level;
    }
    
    /** 
     * Add a parent of the context. That means the parent will be evaluated if 
     * the value of this context changes. 
     *
     * @param parent the parent to be added.
     *
     * @note This function won't add this ContextObject to the children of the
     * parent, because this function is called by the add_child-function of
     * the parent!
     */
    void add_parent(ContextObject* parent);
    
    /**
     * Remove a ContextObject form the parents. 
     *
     * @param name the parent to be removed.
     * 
     * @note This function won't delete this ContextObject from the children
     * of the parent, because this function is called by the
     * remove_child-function of the parent!
     */
    void remove_parent(const string& name);
    
    /**
     * This function sets the level of this node in the context-tree counted
     * from the bottom - the AtomicContexts - which have the level 0. The
     * function will cause its parents to adjust their level.
     *
     * @param level the new level of this ContextObject.
     */
    void set_level(uint32_t level);

    /**
     * Compares the names (strings) of the ContextObjects.
     */
    inline bool operator<(const ContextObject& co) const{
	return name < co.name;
    }

    /**
     * Compares the names (strings) of the ContextObjects.
     */
    inline bool operator>(const ContextObject& co) const{
	return name > co.name;
    }

    /**
     * Compares the names (strings) of the ContextObjects.
     */
    inline bool operator==(const ContextObject& co) const{
	return name == co.name;
    }

    /**
     * Compares the names (strings) of the ContextObjects.
     */
    inline bool operator!=(const ContextObject& co) const{
	return name != co.name;
    }

};
} // namespace context
} // namespace iwear
#endif // __CONTEXTOBJECT_H

