#ifndef TreeDiff_hpp
#define TreeDiff_hpp

#include "TreeElements.hpp"
#include "NodePath.hpp"
#include "INodeListener.hpp"
#include "IComponentListener.hpp"

#include <string>
#include <vector>
#include <set>



namespace apoc { namespace legacy {

enum ActionType 
{ 
    NoAction = 0x0, 
    NodeAdded = 0x1, 
    NodeRemoved = 0x2, 
    NodeChanged = 0x4 
} ; 

class Listeners ;

class DiffListener 
{ 
    public: 
        DiffListener(const std::string& aComponent):mComponent(aComponent) {} ; 
        
        void addListener(const NodePath& aPath, INodeListener *aListener) ; 
        bool removeListener(const NodePath& aPath, INodeListener *aListener) ; 
        void addListener(IComponentListener *aListener) ; 
        bool removeListener(IComponentListener *aListener) ; 
        
        void callAddedListeners(const NodePath& aPath) const ; 
        void callRemovedListeners(const NodePath& aPath) const ; 
        void callChangedListeners(const NodePath& aPath) const ; 
        void callComponentListeners(void) const ; 

        bool hasListeners(const NodePath& aPath) const ;
        bool hasComponentListeners(void) { 
            return !mComponentListeners.empty() ; 
        }

    private: 
        std::string mComponent; 
        std::map<std::string, Listeners *> mListeners ; 
        std::set<IComponentListener *> mComponentListeners ; 
        
        void callListeners(const NodePath& aPath, ActionType aType ) const ; 
}; 

class TreeDiff: public ITreeHandler, public NodeVisitor 
{ 
    public: 
        TreeDiff(const std::string& aComponent, 
                 const DiffListener* aDiffListener, 
                 Tree *aTree = NULL) ; 
        virtual ~TreeDiff() {}
        
        virtual void startTree(void) ; 
        virtual void endTree(void) ; 
        virtual void modifyNode(const std::string& aName, int aAttributes) ; 
        virtual void replaceNode(const std::string& aName, int aAttributes) ; 
        virtual void removeNode(const std::string& aName) ; 
        virtual void endNode(void) ; 
        virtual void modifyProperty(const std::string& aName, 
                                    PropertyType aType, int aAttributes) ; 
        virtual void replaceProperty(const std::string& aName, 
                                     PropertyType aType, int aAttributes) ; 
        virtual void endProperty(void) ;
        virtual void setStringValue(
                                const std::string& aValue, 
                                const std::string& aLocale = kDefaultLocale) ; 
        virtual void setListValue(const std::vector<std::string>& aValue, 
                                  const std::string& aLocale = kDefaultLocale) ;
        virtual void addListValues(
                                const std::vector<std::string>& aValues, 
                                const std::string& aLocale = kDefaultLocale) ; 
        virtual bool preChildrenProcess(Node& aNode) ; 
        virtual bool postChildrenProcess(Node& aNode) ; 
    
    protected: 
    
    private: 
        bool mFindingBaseNode; 
        const std::string mComponent; 
        const DiffListener *mDiffListener; 
        Tree *mTree; 
        bool mInTree; 
        std::vector<std::string> mPathComponents; 
        std::vector<ActionType> mActions; 
} ; 

} } ; // apoc.legacy

#endif // TreeDiff_hpp

