#include <map>
#include <list>

#include "wstring.hh"
#include "autoptr"

typedef autoptr<class XMLTree> XMLTreeP;

class XMLTree: public ptrable
{
public:
    // tags
    typedef std::multimap<std::u32string, XMLTreeP> tagmap_t;
    tagmap_t tags;
    // current tag params
    typedef std::map<std::u32string, std::u32string> parammap_t;
    parammap_t params;
    // tag value
    std::u32string value;

    class XMLTreeSet operator[] (const std::u32string&) const;

    template<typename Func>
    void ForEach(const std::u32string& key, Func f) const;
};

const XMLTree ParseXML(const std::string& s);

class XMLTreeSet
{
public:
    const XMLTreeSet operator[] (const std::u32string&) const;

    operator const std::u32string () const;
    //operator const XMLTreeP () const;

    template<typename Func>
    void ForEach(const std::u32string& key, Func f) const
    {
        for(std::list<XMLTreeP>::const_iterator
            i = matching_trees.begin();
            i != matching_trees.end();
            ++i)
        {
            const XMLTree& p = *(*i);
            p[key].Iterate(f);
        }
    }

    void Iterate(void (*func)(XMLTreeP)) const;
    void Iterate(void (*func)(const std::u32string& )) const;

protected:
    friend class XMLTree;
    void AddTree(XMLTreeP p);
    void SetValue(const std::u32string& s);
    void Combine(const XMLTreeSet& b);

private:
    std::list<XMLTreeP> matching_trees;
    std::list<std::u32string> matching_strings;
};

template<typename Func>
void XMLTree::ForEach(const std::u32string& key, Func f) const
{
    (*this)[key].Iterate(f);
}
