#include "SvgNode.h"

#include "CircleNode.h"
#include "PathNode.h"

#include "SvgElement.h"
#include "SvgShapeElements.h"

SvgNode::SvgNode(const Transform& transform)
    : MaterialNode(transform)
{

}

void SvgNode::setContent(std::unique_ptr<SvgDocument> doc)
{
    mContent = std::move(doc);
    mContentDirty = true;

    mChildren.clear();
    mGeometryNodes.clear();
}

unsigned SvgNode::getContentWidth() const
{
    return mContentWidth;
}

unsigned SvgNode::getContentHeight() const
{
    return mContentHeight;
}

void SvgNode::createOrUpdateGeometry(SceneInfo*)
{
    if (!mContent->getRoot())
    {
        return;
    }

    //auto viewbox = mContent->getViewBox();

    for (const auto& svg_element : mContent->getRoot()->getChildren())
    {
        std::unique_ptr<GeometryNode> geom_node;

        if (svg_element->getTagName() == "circle")
        {
            onCircle(svg_element.get(), geom_node);
        }
        else if (svg_element->getTagName() == "path")
        {
            onPath(svg_element.get(), geom_node);
        }

        AbstractVisualNode* raw_node{ nullptr };
        if (geom_node)
        {
            raw_node = geom_node.get();
            mGeometryNodes.push_back(std::move(geom_node));
        }

        if (raw_node)
        {
            addChild(raw_node);
        }
    }
}

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

    if (mMaterialIsDirty)
    {
        if (mMaterial->hasFillColor())
        {
            for (const auto& geom_node : mGeometryNodes)
            {
                geom_node->setFillColor(mMaterial->getFillColor());
            }
        }
        else
        {
            for (const auto& geom_node : mGeometryNodes)
            {
                geom_node->setHasFillColor(false);
            }
        }

        if (mMaterial->hasStrokeColor())
        {
            for (const auto& geom_node : mGeometryNodes)
            {
                geom_node->setStrokeColor(mMaterial->getStrokeColor());
            }
        }
        else
        {
            for (const auto& geom_node : mGeometryNodes)
            {
                geom_node->setHasStrokeColor(false);
            }
        }
        mMaterialIsDirty = false;
    }
}

void SvgNode::onCircle(XmlElement* element, std::unique_ptr<GeometryNode>& node)
{
    auto svg_circle = dynamic_cast<SvgCircle*>(element);
    auto loc = svg_circle->getLocation();
    auto radius = svg_circle->getRadius();
    auto minor_radius = radius;

    if (svg_circle->getType() == SvgCircle::Type::ELLIPSE)
    {
        minor_radius = svg_circle->getMinorRadius();
    }

    if (element->hasAttribute("transform"))
    {
        const auto transform = svg_circle->getTransform();
        loc.move(transform.getLocation().getX(), transform.getLocation().getY());
        radius *= transform.getScale().mX;
        minor_radius *= transform.getScale().mY;
    }

    auto circle_node = std::make_unique<CircleNode>(loc, radius);
    circle_node->setMinorRadius(minor_radius);
    node = std::move(circle_node);
}

void SvgNode::onPath(XmlElement* element, std::unique_ptr<GeometryNode>& node)
{
    auto svg_path = dynamic_cast<SvgPath*>(element);

    Point loc;
    auto path_node = std::make_unique<PathNode>(loc, svg_path->getPath());
    node = std::move(path_node);
}
