/**
 * @file
 * $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 __COMPOSITECONTEXT_H
#define __COMPOSITECONTEXT_H

#ifndef __CONTEXTOBJECT_H
#include <iwear-context/contextobject.h>
#endif

#ifndef __CONTEXTMAMAGER_H
#include <iwear-context/contextmanager.h>
#endif

#include <string>
#include <stdint.h>
#include <vector>

using namespace std;

namespace iwear{
namespace context {

// forward declaration
class ContextManager;

/**
 * This class implements a composite context that has children that are needed
 * to resolve the context. This makes it possible to construct more complex
 * contexts.
 */
class CompositeContext : public ContextObject{
private:
protected:
    /**
     * The subnodes of this context by their name.
     */
    map<const string, ContextObject*> children;

    /**
     * The subtype of the composite context.
     */
    CompositeType composite_type;
public:
    /**
     * The constructor to be used.
     *
     * @param name the contexts name.
     *
     * @param composite_type the subtype of this context
     *
     * @param level the level in the context-tree. Preinitialized with 1.
     */
    CompositeContext(const string& name,
		     CompositeType composite_type,
		     uint32_t level = 1)
	: ContextObject(name, COMPOSITE, level),
	  composite_type(composite_type)
    {
	
    }

    /**
     * The destructor of this class.
     */
    virtual ~CompositeContext(void);

    /**
     * Adds a given ContextObject to the children of this context. The level
     * of this context and the levels of its parents will be adjusted properly
     * if necessary.
     *
     * @param co the child to be added. 
     */
    void add_child(ContextObject* co);

    /**
     * Removes a given ContextObject from the children of this context. The
     * level of this context and the levels of its parents will be adjusted
     * properly if necessary.
     *
     * @param co the child to be removed. 
     */
    void remove_child(const string& name);

    /**
     * Checks if the level of this context is still one above the max-level of
     * all the children - if not the level is corrected and the
     * check_level-function of the parents of this context is called.
     */
    void check_level(void);

    /**
     * Called from the ContextManager when a new CompositeContext is registered so 
     * also the children are known afterwards.
     *
     * @return if all the children have been registered successfully.
     */
    bool register_children(ContextManager* cm);
    
    /**
     * This function evaluates this context by getting the values of the
     * children and combining them to the value of this context - the new
     * value is NOT returned.
     *
     * @return true if the context has changed since the last call of this function.
     */
    virtual bool resolve_context(void) = 0;

    /**
     * Compares two CompositeContexts according to their level.
     */
    bool operator<(const CompositeContext& cc) const{
	return level < cc.level;
    }

    /**
     * Get a list of all the atomic contexts that are (direct or indirect)
     * children of this CompositeContext.
     *
     * @return all AtomicContexts that are subnodes of this.
     */
    std::vector<AtomicContext*> get_related_atomics(void);

    /**
     * Get the children of this CompositeContext.
     *
     * @return the children related to this context.
     */
    map<const string, ContextObject*>& get_children(void){
	return children;
    }

    /**
     * Get the subtype of the context.
     *
     * @return the subtype of the context.
     */
    CompositeType get_composite_type(void) const{
	return composite_type;
    }

}; // class ComposisteContext

} // namespace context
} // namespace iwear
#endif	// __COMPOSITECONTEXT_H

