#pragma once

#include "TemplateNode.h"

class TemplateExtends : public TemplateNode
{
public:
    TemplateExtends(TemplateNode* parent, const std::string& path);

    virtual ~TemplateExtends() = default;

    std::string getRawContent() const override;
    std::string getPath() const;

    Type getType() const override
    {
        return Type::EXTENDS;
    }

private:
    std::string mPath;
};

class TemplateBlock : public TemplateNode
{
public:
    TemplateBlock(TemplateNode* parent, const std::string& name);

    virtual ~TemplateBlock() = default;

    void addLine(const std::string& line);

    std::string getRawContent() const override;

    std::string getIdentifier() const override;

    Type getType() const override
    {
        return Type::BLOCK;
    }

    std::string renderAsParent(TemplateSubstitutionContext* substitutions, TemplateBlock* base);

    std::string renderAsLeaf(TemplateSubstitutionContext* substitutions);

    std::string render(TemplateSubstitutionContext* substitutions, TemplateNode* parentContext) override;

private:
    std::string mName;
    std::vector<std::string> mBody;
};

class TemplateExpression : public TemplateNode
{
public:
    TemplateExpression(TemplateNode* parent, const std::string& content);

    virtual ~TemplateExpression() = default;

    std::string getRawContent() const override;

    const std::string& getContent() const;

    Type getType() const override
    {
        return Type::EXPRESSION;
    }

    std::string render(TemplateSubstitutionContext* substitutions, TemplateNode* parentContext) override;

private:
    std::string mContent;
};

class TemplateTextBody : public TemplateNode
{
public:
    TemplateTextBody(TemplateNode* parent);

    virtual ~TemplateTextBody() = default;

    void addLine(const std::string& content);

    std::string getRawContent() const override;

    bool hasContent() const;

    std::string render(TemplateSubstitutionContext* substitutions, TemplateNode* parentContext) override;

    Type getType() const override
    {
        return Type::TEXT_BODY;
    }
private:
    std::vector<std::string> mContent;
};
