#include "TemplatingEngine.h"

#include "Directory.h"
#include "FileLogger.h"

#include "TemplateElements.h"
#include "TemplateSubstitutionContext.h"

#include <iostream>

TemplatingEngine::TemplatingEngine(const Path& workingDirectory)
    : mWorkingDirectory(workingDirectory)
{

}

std::string TemplatingEngine::renderTemplate(const std::string& name, TemplateSubstitutionContext* substitutionContext)
{
    if (mTemplateFiles.empty())
    {
        loadTemplateFiles();
    }

    if (auto file = getTemplateFile(name))
    {
        if (!file->hasLoaded())
        {
            file->loadContent();
            std::cout << file->dumpContent();

            processTemplate(file, nullptr);
        }

        return file->getContent()->render(substitutionContext, nullptr);
    }
    else
    {
        return {};
    }

}

void TemplatingEngine::loadTemplateFiles()
{
    const auto files = Directory::getFilesWithExtension(mWorkingDirectory, mTemplateExtension);
    for (const auto& path : files)
    {
        mTemplateFiles[path.stem().string()] = std::make_unique<TemplateFile>(path);
    }
    MLOG_INFO("Found: " << mTemplateFiles.size() << " templates in " << mWorkingDirectory);
}

TemplateFile* TemplatingEngine::getTemplateFile(const Path& path)
{
    return getTemplateFile(path.stem().string());
}

TemplateFile* TemplatingEngine::getTemplateFile(const std::string& name)
{
    return mTemplateFiles[name].get();
}

void TemplatingEngine::processTemplate(TemplateFile* file, TemplateNode* parent)
{
    std::cout << "Processing file " << file->getName() << std::endl;

    auto content = file->getContent();
    if (parent)
    {
        std::cout << "Setting extension parent" << std::endl;
        content->setExtensionParent(parent);
    }

    if (auto extension_node = dynamic_cast<TemplateExtends*>(content->getFirstChildShallow(TemplateNode::Type::EXTENDS)))
    {
        std::cout << "Found extension node " << std::endl;
        if (auto extension_template = getTemplateFile(Path(extension_node->getPath())))
        {
            std::cout << "Found extension template " << std::endl;
            processTemplate(extension_template, content);
        }
    }
}
