#pragma once

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

class TemplateSubstitutionContext;

class TemplateNode
{
public:
    enum class Type
    {
        NONE,
        BLOCK,
        EXPRESSION,
        EXTENDS,
        TEXT_BODY
    };

    TemplateNode(TemplateNode* parent);

    virtual ~TemplateNode() = default;

    virtual void addChild(std::unique_ptr<TemplateNode> child);

    TemplateNode* getChild(std::size_t index) const;

    TemplateNode* getFirstChildShallow(Type type, const std::string& identifier = {}) const;

    virtual std::string getIdentifier() const;

    std::size_t getNumChildren() const;

    TemplateNode* getParent() const;

    virtual std::string getRawContent() const;

    virtual Type getType() const;

    virtual std::string render(TemplateSubstitutionContext* substitutions, TemplateNode* parentContext = nullptr);

    void setExtensionParent(TemplateNode* parent);

protected:
    std::vector<std::unique_ptr<TemplateNode> > mChildren;
    TemplateNode* mParent{ nullptr };
    TemplateNode* mExtensionParent{ nullptr };
};

using TemplateNodePtr = std::unique_ptr<TemplateNode>;
