#include "EquationNode.h"

#include "LatexMathExpression.h"
#include "TextNode.h"
#include "LineNode.h"

#include "FileLogger.h"

EquationNode::EquationNode(const Transform& t)
	: AbstractVisualNode(t)
{

}

EquationNode::~EquationNode()
{

}

void EquationNode::setContent(LatexMathExpression* content)
{
	mContent = content;
	mContentDirty = true;
}

void EquationNode::update(SceneInfo* sceneInfo)
{
    if (mContentDirty)
    {
        createOrUpdateGeometry(sceneInfo);
        mContentDirty = false;
    }
}

void EquationNode::addExpression(SceneInfo* sceneInfo, const LatexMathExpression* expression)
{
    if (expression->getType() == LatexMathExpression::Type::LINEAR)
    {
        MLOG_INFO("Processing linear expr with : " << expression->getExpressions().size() << " children");
        for (const auto& child : expression->getExpressions())
        {
            addExpression(sceneInfo, child.get());
        }
    }
    else if(expression->getType() == LatexMathExpression::Type::LEAF)
    {
        std::string content;
        for (const auto& symbol : expression->getSymbols())
        {
            content += symbol.mUnicode;
        }

        if (content.empty())
        {
            return;
        }

        MLOG_INFO("Processing leaf expr with content: " << content << " and size " << content.size());
        auto node = std::make_unique<TextNode>(content, Transform(mTextCursor));
        node->setFont(mDefaultFont);
        addChild(node.get());

        mTextCursor.move(node->getContentWidth(sceneInfo), 0.0);

        mText.push_back(std::move(node));  
    }
    else if (expression->getType() == LatexMathExpression::Type::FRACTION)
    {
        MLOG_INFO("Processing frac expr");
        if (expression->getExpressions().size() == 2)
        {
            auto x_cache = mTextCursor.getX();
            mTextCursor.move(0.0, -9.0);
            addExpression(sceneInfo, expression->getExpressions()[0].get());

            mTextCursor.move(x_cache - mTextCursor.getX(), 16.0);
            std::vector<Point> end_loc{ { 25.0, 0.0 } };
            auto dividing_line = std::make_unique<LineNode>(Transform(mTextCursor), end_loc);
            addChild(dividing_line.get());
            mLines.push_back(std::move(dividing_line));

            mTextCursor.move(0.0, 2.0);
            addExpression(sceneInfo, expression->getExpressions()[1].get());

            mTextCursor.move(0.0, -9.0);
        }
    }
    else if (expression->getType() == LatexMathExpression::Type::ENCLOSING)
    {
        MLOG_INFO("Processing enclosing expr");
        if (expression->getExpressions().size() == 1)
        {
            auto left_content = expression->getLeftSymbol().mUnicode;

            auto left_node = std::make_unique<TextNode>(left_content, Transform(mTextCursor));
            left_node->setFont(mDefaultFont);
            addChild(left_node.get());

            mTextCursor.move(left_node->getContentWidth(sceneInfo), 0.0);
            mText.push_back(std::move(left_node));

            addExpression(sceneInfo, expression->getExpressions()[0].get());

            auto right_content = expression->getRightSymbol().mUnicode;

            auto right_node = std::make_unique<TextNode>(right_content, Transform(mTextCursor));
            right_node->setFont(mDefaultFont);
            addChild(right_node.get());

            mTextCursor.move(right_node->getContentWidth(sceneInfo), 0.0);

            mText.push_back(std::move(right_node));
        }
    }
}

void EquationNode::createOrUpdateGeometry(SceneInfo* sceneInfo)
{
    mChildren.clear();
    mText.clear();

    addExpression(sceneInfo, mContent);
}