#include "TextNode.h"

#include "Rectangle.h"
#include "FontsManager.h"
#include "IFontEngine.h"
#include "MeshPrimitives.h"
#include "FontItem.h"
#include "FontGlyph.h"

#include "SceneText.h"

#include "Color.h"

#include "StringUtils.h"

#include <iostream>

TextNode::TextNode(const std::string& content, const DiscretePoint& loc)
    :   MaterialNode(loc)
{
    mTextData.mContent= content;
}

TextNode::~TextNode()
{

}

std::unique_ptr<TextNode> TextNode::Create(const std::string& content, const DiscretePoint& loc)
{
    return std::make_unique<TextNode>(content, loc);
}

std::string TextNode::getFontLabel() const
{
    return {};
}

std::string TextNode::getContent() const
{
    return mTextData.mContent;
}

unsigned TextNode::getWidth() const
{
    return mWidth;
}

unsigned TextNode::getHeight() const
{
    return mHeight;
}

void TextNode::setWidth(unsigned width)
{
    if (mWidth != width)
    {
        mTransformIsDirty = true;
        mWidth = width;
    }
}

void TextNode::setHeight(unsigned height)
{
    if (mHeight != height)
    {
        mTransformIsDirty = true;
        mHeight = height;
    }
}

void TextNode::setContent(const std::string& content)
{
    if (mTextData.mContent != content)
    {
        mTextData.mContent = content;
        mContentIsDirty = true;
    }
}

SceneItem* TextNode::getSceneItem(std::size_t idx) const
{
    if (idx == 0)
    {
        return mTextItem.get();
    }
    else
    {
        return 0;
    }
}

unsigned TextNode::getNumSceneItems() const
{
    return 1;
}

void TextNode::updateLines(FontsManager* fontsManager)
{
    auto original_count = mTextData.mLines.size();
    std::vector<std::string> lines = StringUtils::toLines(mTextData.mContent);
    std::vector<std::string> output_lines;
    for (auto line : lines)
    {
        double running_width{0};
        std::string working_line;
        for (auto c : line)
        {
            auto glyph_advance = fontsManager->getGlyph(mTextData.mFont.getFaceName(), mTextData.mFont.getSize(), c)->getAdvanceX();
            if (false)
            //if (running_width + glyph_advance > mWidth)
            {
                output_lines.push_back(working_line);
                working_line = c;
                running_width = glyph_advance;
            }
            else
            {
                working_line += c;
                running_width += glyph_advance;
            }
        }
        output_lines.push_back(working_line);
        running_width = 0;
    }
    mTextData.mLines = output_lines;

    if (original_count != mTextData.mLines.size())
    {
        mLinesAreDirty = true;
    }
}

void TextNode::update(FontsManager* fontsManager)
{
    if (!mTextItem)
    {
        mTextItem = std::make_unique<SceneText>();
        mTextItem->setName(mName + "_SceneText");
    }

    if (mTransformIsDirty || mContentIsDirty)
    {
        updateLines(fontsManager);
    }

    if (mContentIsDirty || mLinesAreDirty)
    {
        dynamic_cast<SceneText*>(mTextItem.get())->setTextData(mTextData);
        mContentIsDirty = false;
        mLinesAreDirty = false;
    }

    if (mTransformIsDirty)
    {
        mTextItem->updateTransform({mLocation});
        mTransformIsDirty = false;
    }

    if (mMaterialIsDirty)
    {
        mTextItem->updateUniformColor(mFillColor);
        mMaterialIsDirty = false;
    }
}
