#pragma once

#include <memory>
#include <vector>
#include <string>
#include <unordered_map>

class XmlAttribute;
using XmlAttributePtr = std::unique_ptr<XmlAttribute>;

class XmlElement
{
public:
    XmlElement(const std::string& tagName);
    virtual ~XmlElement();

    static std::unique_ptr<XmlElement> Create(const std::string& tagName);

    void addAttribute(XmlAttributePtr attribute);
    void addAttribute(const std::string& name, const std::string& value);
    void addChild(std::unique_ptr<XmlElement> child);

    const std::string& getTagName() const;
    const std::string& getText() const;

    bool hasAttribute(const std::string& attribute) const;
    XmlAttribute* getAttribute(const std::string& attribute) const;
    const std::unordered_map<std::string, XmlAttributePtr>& getAttributes() const;

    const std::vector<std::unique_ptr<XmlElement> >& getChildren() const;

    XmlElement* getFirstChildWithTagName(const std::string& tag);

    void setText(const std::string& text);
    void setTagName(const std::string& tagName);

    virtual std::string toString(unsigned depth = 0, bool keepInline = false) const;

protected:
    std::string mTagName;
    std::string mText;

    std::unordered_map<std::string, XmlAttributePtr> mAttributes;
    std::vector<std::unique_ptr<XmlElement> > mChildren;
};

using XmlElementPtr = std::unique_ptr<XmlElement>;
