#ifndef ContextH
#define ContextH

#include <string>
#include <list>
#include <boost/shared_ptr.hpp>
#include <boost/optional.hpp>
#include "context/ContextManager.h"
#include "context/ContextStatus.h"
#include "util/simpleobject/AgDate.h"
#include "util/AgObject.h"
#include "event/FireEventRequestController.h"
#include "util/Pointers.h"

/**
 * Context interface is used to provide a unified way to access any object in AggreGate. It may be some server object (e.g. alert or event filters storage), hardware device or widget component. When
 * server contexts are accessed remotely, so-called proxy contexts are created for operating server-side objects through the same interface.
 */

class Context : public AgObject, public Comparable
{

 public:
    /**
       * This method is called after the context has been added to a context tree and it became aware of its full path. Note, that default implementation of this method in AbstractContext calls tree
       * methods: setupPermissions(), setupMyself() and setupChildren(). These methods should provide initialization logic in inherited classes instead of overridden setup() method.
       *
       * @param ContextManager*          ContextManager heading current context tree
       */
    virtual void setup(ContextManager* contextManager)=0;

    /**
       * This method is called when the context is being removed from context tree..
       *
       * @param contextManager
       *          ContextManager heading current context tree
       */
    virtual void teardown()=0;

    /**
     * This method should return true if the context has already been initialized and setupMyself() finished execution. Its default implementation in AbstractContext should not be overridden.
     *
     * @return true if setupMyself() has already been completed.
     */
    virtual bool isSetupComplete()=0;


    /**
     * This method should return true if the context has already been initialized its basic information (description, type, etc).
     *
     * @return true if basic context information has been initialized.
     */
    virtual bool isInitializedInfo()=0;

    /**
       * This method should return true if the context has already been initialized its children.
       *
       * @return true if context children have been initialized.
       */
    virtual bool isInitializedChildren()=0;


    /**
     * This method should return true if the context has already been initialized its variables.
     *
     * @return true if context variables have been initialized.
     */
	virtual bool isInitializedVariables()=0;

    /**
       * This method should return true if the context has already been initialized its functions.
       *
       * @return true if context functions have been initialized.
       */
	virtual bool isInitializedFunctions()=0;

    /**
     * This method should return true if the context has already been initialized its events.
     *
     * @return true if context events have been initialized.
     */
	virtual bool isInitializedEvents()=0;


    /**
       * This method is called when context tree is being started after its initialization. All contexts in the tree should be available at the moment of call.
       */
    virtual void start()=0;


    /**
     * This method is called when context tree is being stopped before its de-initialization. All contexts in the tree should be available at the moment of call.
     */
    virtual void stop()=0;

    /**
     * Returns true if context was started but not yet stopped.
     */
    virtual bool isStarted()=0;

    /**
       * Returns context name.
    */
    virtual AgString getName()=0;

    /**
     * Returns context path (full name).
     */
    virtual AgString getPath()=0;

    /**
     * Returns path of context's peer in distributed environment.
     */
    virtual AgString getRemotePath()=0;

    /**
     * When a certain context subtree from one server is connected to another server, this method will return the remote path of this subtree's root context. If current context doesn't have a remote
     * peer, this method returns null.
     */
    virtual AgString getRemoteRoot()=0;

    /**
     * Returns true if context is a remote context's proxy.
     */
    virtual bool isProxy()=0;

    /**
     * Returns true if context has a remote peer in the distributed architecture.
     */
    virtual bool isDistributed()=0;

    /**
     * Returns context detailed description that includes description and path.
     */
    virtual AgString toDetailedString()=0;


    /**
     * Returns context description.
     */
    virtual AgString getDescription()=0;

    /**
     * Returns context type.
     */
    virtual AgString getType()=0;

    /**
     * Returns context group name of NULL if context does not belong to a group.
     */
    virtual AgString getGroup()=0;

    /**
     * Returns context comparison index or NULL if index is not defined.
     */
    virtual boost::optional<int> getIndex()=0;

    /**
     * Returns context icon ID.
     */
    virtual AgString getIconId()=0;


  /**
   * Returns context status or null if status is not enabled;
   */
	virtual ContextStatusPtr getStatus()=0;

  /**
   * Returns context manager those context tree contains this context.
   */
    virtual ContextManager* getContextManager()=0;

  /**
   * Returns list of children contexts that are accessible by the specified <code>CallerController</code>.
   */
    virtual std::list<Context *>  getChildren(CallerControllerPtr caller)=0;
	
  /**
   * Returns list of children contexts.
   */
    virtual std::list<Context *>  getChildren()=0;

  /**
   * Returns list of visible children contexts.
   */
    virtual std::list<Context *>  getVisibleChildren(CallerControllerPtr caller)=0;

  /**
   * Returns list of visible children contexts.
   */
    virtual std::list<Context *>  getVisibleChildren()=0;

  /**
   * Returns true if context's visible children are mapped (e.g. for group and aggregation contexts).
   */
	virtual bool isMapped()=0;

  /**
   * Returns list of mapped children contexts.
   */
    virtual std::list<Context *>  getMappedChildren(CallerControllerPtr caller)=0;
	
  /**
   * Returns list of mapped children contexts.
   */
    virtual std::list<Context*>  getMappedChildren()=0;
	
  /**
   * Returns root context of the context tree containing this context.
   */
    virtual Context* getRoot()=0;
  /**
   * Returns context with the selected path.
   * 
   * <code>path</code> argument may be absolute of relative to this context. This method uses provided <code>CallerController</code> for permission checking.
   */
    virtual Context* get(const AgString & path, CallerControllerPtr caller)=0;
  /**
   * Returns context with the selected path.
   * 
   * <code>path</code> argument may be absolute of relative to this context.
   * 
   * Note: if this Context is a part of distributed context tree and path argument is not relative, the method will return local context matching its remote "peer" with given path. To get the local
   * context with the given path, use {@link ContextManager#get(String)} instead.
   */
    virtual Context* get(const AgString & path)=0;
  /**
   * Returns child of this context with the specified name.
   * 
   * <code>path</code> argument may be absolute of relative to this context.
   * 
   * Note: if this Context is a part of distributed context tree and path argument is not relative, the method will return local context matching its remote "peer" with given path. To get the local
   * context with the given path, use {@link ContextManager#get(String, CallerController)} instead.
   * 
   * This method uses provided <code>CallerController</code> for permission checking.
   */
    virtual Context* getChild(const AgString & name, CallerControllerPtr caller)=0;
  /**
   * Returns child of this context with the specified name.
   */
    virtual Context* getChild(const AgString & name)=0;
	
  /**
   * Adds new child to the current context.
   */
    virtual void addChild(Context *child)=0;

  /**
   * Removes child of current context.
   */
    virtual void removeChild(Context* child)=0;

  /**
   * Removes child with specified name.
   */
    virtual void removeChild(const AgString & name)=0;
  /**
   * Permanently destroys child of current context.
   */
    virtual void destroyChild(Context* child, bool moving)=0;

  /**
   * Permanently destroys child with specified name.
   */
    virtual void destroyChild(const AgString & name, bool moving)=0;

  /**
   * Permanently destroys this context.
   */
	virtual void destroy(bool moving)=0;

  /**
   * Moves and/or renames the context.
   */
    virtual void move(Context* newParent, const AgString & newName)=0;
    virtual void setParent(Context* parent)=0;
	
	
  /**
   * Returns parent of this context.
   */
    virtual Context* getParent()=0;

  /**
   * Returns true if parentContext is a parent of this context or some of its parents.
   */
    virtual bool hasParent(Context *parentContext)=0;
	
  /**
   * Adds variable definition to this context.
   */
	virtual void addVariableDefinition(VariableDefinitionPtr def)=0;

  /**
   * Removes variable definition from this context.
   */
    virtual void removeVariableDefinition(const AgString & name)=0;
  /**
   * Returns data of variable with specified name.
   */
    virtual VariableDataPtr getVariableData(const AgString & name)=0;
  /**
   * Returns definition of variable with specified name.
   */
    virtual VariableDefinitionPtr getVariableDefinition(const AgString & name)=0;
  /**
   * Returns definition of variable with specified name if it's accessible by caller controller.
   */
    virtual VariableDefinitionPtr getVariableDefinition(const AgString & name, CallerControllerPtr caller)=0;
  /**
   * Returns list of variables available for specified <code>CallerController</code>.
   */
	virtual std::list<VariableDefinitionPtr>  getVariableDefinitions(CallerControllerPtr caller)=0;
  /**
   * Returns list of variables.
   */
    virtual std::list<VariableDefinitionPtr>  getVariableDefinitions()=0;
  /**
   * Returns list of variables belonging to <code>group</code> that are available for specified <code>CallerController</code>.
   */
    virtual std::list<VariableDefinitionPtr>  getVariableDefinitions(CallerControllerPtr caller, const AgString & group)=0;
  /**
   * Returns list of variables belonging to <code>group</code>.
   */
    virtual std::list<VariableDefinitionPtr>  getVariableDefinitions(const AgString & group)=0;
  /**
   * Returns list of variables.
   */
	virtual std::list<VariableDefinitionPtr>  getVariableDefinitions(CallerControllerPtr caller, bool includeHidden)=0;
  /**
   * Adds function definition to this context.
   */
	virtual void addFunctionDefinition(FunctionDefinitionPtr def)=0;
  /**
   * Removes function definition from this context.
   */
    virtual void removeFunctionDefinition(const AgString & name)=0;
  /**
   * Returns data of function with specified name.
   */
    virtual FunctionDataPtr getFunctionData(const AgString & name)=0;
  /**
   * Returns definition of function with specified name.
   */
    virtual FunctionDefinitionPtr getFunctionDefinition(const AgString & name)=0;

  /**
   * Returns definition of function with specified name if it's accessible by caller controller.
   */
    virtual FunctionDefinitionPtr getFunctionDefinition(const AgString & name, CallerControllerPtr caller)=0;

  /**
   * Returns list of functions available for specified <code>CallerController</code>.
   */
	virtual std::list< FunctionDefinitionPtr >  getFunctionDefinitions(CallerControllerPtr caller)=0;
  /**
   * Returns list of functions.
   */
	virtual std::list< FunctionDefinitionPtr >  getFunctionDefinitions()=0;
  /**
   * Returns list of functions belonging to <code>group</code> that are available for specified <code>CallerController</code>.
   */
    virtual std::list< FunctionDefinitionPtr >  getFunctionDefinitions(CallerControllerPtr caller, const AgString & group)=0;
  /**
   * Returns list of functions belonging to <code>group</code>.
   */
    virtual std::list< FunctionDefinitionPtr >  getFunctionDefinitions(const AgString & group)=0;

  /**
   * Returns list of functions.
   */
	virtual std::list< FunctionDefinitionPtr >  getFunctionDefinitions(CallerControllerPtr caller, bool includeHidden)=0;

  /**
   * Adds event definition to this context.
   */
	virtual void addEventDefinition(EventDefinitionPtr def)=0;
  /**
   * Removes event definition from this context.
   */
    virtual void removeEventDefinition(const AgString & name)=0;
  /**
   * Returns definition of event with specified name.
   */
    virtual  EventDefinitionPtr getEventDefinition(const AgString & name)=0;

  /**
   * Returns definition of event with specified name if it's accessible by caller controller.
   */
    virtual  EventDefinitionPtr getEventDefinition(const AgString & name, CallerControllerPtr caller)=0;

  /**
   * Returns <code>EventDataPtr</code> of event with specified name.
   */
    virtual EventDataPtr getEventData(const AgString & name)=0;
  /**
   * Returns list of events available for specified <code>CallerController</code>.
   */
	virtual std::list< EventDefinitionPtr >  getEventDefinitions(CallerControllerPtr caller)=0;
  /**
   * Returns list of events.
   */
	virtual std::list< EventDefinitionPtr >  getEventDefinitions()=0;
  /**
   * Returns list of events belonging to <code>group</code> that are available for specified <code>CallerController</code>.
   */
    virtual std::list< EventDefinitionPtr >  getEventDefinitions(CallerControllerPtr caller, const AgString & group)=0;
 /**
   * Returns list of events belonging to <code>group</code>.
   */
    virtual std::list< EventDefinitionPtr >  getEventDefinitions(const AgString & group)=0;
  /**
   * Returns list of events.
   */
	virtual std::list< EventDefinitionPtr >  getEventDefinitions(CallerControllerPtr caller, bool includeHidden)=0;
  /**
   * Gets variable from context and returns its value.
   */
    virtual DataTablePtr getVariable(const AgString & name, CallerControllerPtr caller, RequestControllerPtr request)=0;

   /**
    * Gets variable from context and returns its value.
    */
    virtual DataTablePtr getVariable(const AgString& name, CallerControllerPtr caller) = 0;

  /**
   * Gets variable from context and returns its value.
   */
    virtual DataTablePtr getVariable(const AgString & name)=0;
	
	  /**
   * Returns value of variable as bean or list of beans.
   */
    virtual AgObjectPtr getVariableObject(const AgString & name, CallerControllerPtr caller)=0;

	  /**
   * Sets context variable to specified <code>value</code>.
   */
    virtual void setVariable(const AgString & name, CallerControllerPtr caller, DataTablePtr value)=0;
	  /**
   * Sets context variable to specified <code>value</code>.
   */
    virtual void setVariable(const AgString & name, CallerControllerPtr caller, RequestControllerPtr request, DataTablePtr value)=0;
	  /**
   * Sets context variable to specified <code>value</code>.
   */
    virtual void setVariable(const AgString & name, CallerControllerPtr caller, std::list<AgObjectPtr> value) =0;
	  /**
   * Sets context variable to specified <code>value</code>.
   */
    virtual void setVariable(const AgString & name, DataTablePtr value) =0;
	  /**
   * Sets context variable to specified <code>value</code>.
   */
    virtual void setVariable(const AgString & name, std::list<AgObjectPtr> value) =0;
	
	  /**
   * Gets variable, updates field value in the first record, and sets variable.
   */
    virtual bool setVariableField(const AgString & variable, const AgString & field, AgObjectPtr value, CallerControllerPtr cc) =0;
	  /**
   * Gets variable, updates field value in the specified record, and sets variable.
   */
    virtual bool setVariableField(const AgString & variable, const AgString & field, int record, AgObjectPtr value, CallerControllerPtr cc) =0;
	  /**
   * Gets variable, updates field value in the records for those value of compareField equals compareValue, and sets variable.
   */
    virtual void setVariableField(const AgString & variable, const AgString & field, AgObjectPtr value, const AgString & compareField, AgObjectPtr compareValue, CallerControllerPtr cc) =0;
	
	/**
   * Executes context function with specified <code>parameters</code> and returns its output.
   */
    virtual DataTablePtr callFunction(const AgString & name, CallerControllerPtr caller, DataTablePtr parameters)=0;

    virtual DataTablePtr callFunction(const AgString & name, DataTablePtr parameters)=0;

    virtual DataTablePtr callFunction(const AgString & name)=0 ;

    virtual DataTablePtr callFunction(const AgString & name, CallerControllerPtr caller, RequestControllerPtr request, DataTablePtr parameters)=0 ;

    virtual DataTablePtr callFunction(const AgString & name, CallerControllerPtr caller, std::list<AgObjectPtr> parameters)=0 ;
    
    virtual DataTablePtr callFunction(const AgString & name, std::list<AgObjectPtr> parameters)=0 ;
    
    virtual DataTablePtr callFunction(const AgString & name, CallerControllerPtr caller)=0 ;
    

  /**
   * Fires context event.
   * 
   * @return Event object or null if event was suppressed by context.
   */
    virtual EventPtr fireEvent(const AgString & name)=0;
    virtual EventPtr fireEvent(const AgString & name, CallerControllerPtr caller)=0;
    virtual EventPtr fireEvent(const AgString & name, DataTablePtr data)=0;
    virtual EventPtr fireEvent(const AgString & name, CallerControllerPtr caller, DataTablePtr data)=0;
    virtual EventPtr fireEvent(const AgString & name, int level, DataTablePtr data)=0;
    virtual EventPtr fireEvent(const AgString & name, int level, CallerControllerPtr caller, DataTablePtr data)=0;
    virtual EventPtr fireEvent(const AgString & name, std::list<AgObjectPtr> data)=0;
    virtual EventPtr fireEvent(const AgString & name, DataTablePtr data, int level, int64_t id, AgDatePtr creationtime, int  listener, CallerControllerPtr caller, FireEventRequestControllerPtr request)=0;
   
    /**
   * Add a new action definition to the context.
   * 
   * @param def
   *          ActionDefinition to add
   */
	virtual void addActionDefinition(ActionDefinitionPtr def)=0;
   /**
   * Remove an action definition from the context.
   * 
   * @param name
   *          Name of action to remove
   */
    virtual void removeActionDefinition(const AgString & name)=0;
    /**
   * Returns action definition by name.
   * 
   * @param name
   *          Name of ActionPtr
    virtual ActionDefinitionPtr getActionDefinition(const AgString & name)=0;
    virtual ActionDefinitionPtr getActionDefinition(const AgString & name, CallerControllerPtr caller)=0;
    */
    /**
   * Returns default action definition or NULL if there is no default action or it's not available to the caller.
   * 
   * @param caller
   */
	virtual ActionDefinitionPtr getDefaultActionDefinition(CallerControllerPtr caller)=0;
  /**
   * Returns action definitions.
   */
   virtual  std::list< ActionDefinitionPtr >  getActionDefinitions()=0;
  /**
   * Returns action definitions that are accessible for the caller.
   * 
   * @param caller
   */
	virtual std::list< ActionDefinitionPtr >  getActionDefinitions(CallerControllerPtr caller)=0;
	virtual std::list< ActionDefinitionPtr >  getActionDefinitions(CallerControllerPtr caller, bool includeHidden)=0;
   /**
   * Returns context permissions.
   */
	virtual PermissionsPtr getPermissions()=0;
   /**
   * Returns permissions required to access children of this context.
   */
	virtual PermissionsPtr getChildrenViewPermissions()=0;



  /**
   * Adds listener of event with specified name.
   */
    virtual bool addEventListener(const AgString & name, ContextEventListenerPtr listener)=0;
 
  /**
   * Adds listener of event with specified name. This method allows to add auto-cleaned listeners by setting weak flag to true.
   */
    virtual bool addEventListener(const AgString & name, ContextEventListenerPtr listener, bool weak)=0;

  /**
   * Removes listener of event with specified name.
   */
    virtual  bool removeEventListener(const AgString & name, ContextEventListenerPtr listener)=0;
  /**
   * Returns in-memory event history.
   */
    virtual std::list<EventPtr>  getEventHistory(const AgString & name)=0;
  /**
   * Accepts context visitor, i.e. calls visitor.visit(this).
   */
	virtual  void accept(ContextVisitorPtr visitor)=0;

    virtual ~Context() {};

};

#endif
