#include "SvgShapeElements.h"

#include "PointParser.h"
#include <sstream>

SvgCircle::SvgCircle(Type type)
    : SvgShapeElement(type == Type::REGULAR ? "circle" : "ellipse"),
        mType(type)
{

}

Point SvgCircle::getLocation() const
{
    double cx = 0.0;
    double cy = 0.0;
    if (auto attr = getAttribute("cx"); attr)
    {
        cx = std::stod(attr->getValue());
    }
    if (auto attr = getAttribute("cy"); attr)
    {
        cy = std::stod(attr->getValue());
    }
    return { cx, cy };
}

double SvgCircle::getRadius() const
{
    double radius = 1.0;
    if (auto attr = getAttribute("rx"); attr)
    {
        radius = std::stod(attr->getValue());
    }
    else if (auto attr = getAttribute("r"); attr)
    {
        radius = std::stod(attr->getValue());
    }
    return radius;
}

SvgCircle::Type SvgCircle::getType() const
{
    return mType;
}

double SvgCircle::getMinorRadius() const
{
    double radius = 0.0;
    if (auto attr = getAttribute("ry"); attr)
    {
        radius = std::stod(attr->getValue());
    }
    return radius;
}

void SvgCircle::setLocation(const Point& loc)
{
    auto cx = std::make_unique<XmlAttribute>("cx");
    auto cy = std::make_unique<XmlAttribute>("cy");

    cx->setValue(std::to_string(loc.getX()));
    cy->setValue(std::to_string(loc.getY()));

    addAttribute(std::move(cx));
    addAttribute(std::move(cy));
}

void SvgCircle::setRadius(double rad)
{
    if (mType == Type::REGULAR)
    {
        auto r = std::make_unique<XmlAttribute>("r");
        r->setValue(std::to_string(rad));
        addAttribute(std::move(r));
    }
    else
    {
        auto r = std::make_unique<XmlAttribute>("rx");
        r->setValue(std::to_string(rad));
        addAttribute(std::move(r));
    }
}

void SvgCircle::setMinorRadius(double rad)
{
    auto r = std::make_unique<XmlAttribute>("ry");
    r->setValue(std::to_string(rad));
    addAttribute(std::move(r));
}

SvgRectangle::SvgRectangle()
    : SvgShapeElement("rect")
{

}

void SvgRectangle::setLocation(const Point& loc)
{
    auto x = std::make_unique<XmlAttribute>("x");
    auto y = std::make_unique<XmlAttribute>("y");

    x->setValue(std::to_string(loc.getX()));
    y->setValue(std::to_string(loc.getY()));

    addAttribute(std::move(x));
    addAttribute(std::move(y));
}

void SvgRectangle::setWidth(double w)
{
    auto width = std::make_unique<XmlAttribute>("width");

    width->setValue(std::to_string(w));

    addAttribute(std::move(width));
}

void SvgRectangle::setHeight(double h)
{
    auto height = std::make_unique<XmlAttribute>("height");

    height->setValue(std::to_string(h));

    addAttribute(std::move(height));
}

void SvgRectangle::setRadius(double radius)
{
    auto rx = std::make_unique<XmlAttribute>("rx");

    rx->setValue(std::to_string(radius));

    addAttribute(std::move(rx));
}


SvgPolygon::SvgPolygon()
    : SvgShapeElement("polygon")
{

}

void SvgPolygon::setPoints(const std::vector<Point>& locs)
{
    auto points = std::make_unique<XmlAttribute>("points");

    std::stringstream sstr;
    for (const auto& loc : locs)
    {
        sstr << loc.getX() << "," << loc.getY() << " ";
    }
    points->setValue(sstr.str());
    addAttribute(std::move(points));
}

SvgPolyline::SvgPolyline()
    : SvgShapeElement("polyline")
{
    auto fill = std::make_unique<XmlAttribute>("fill");
    fill->setValue("none");
    addAttribute(std::move(fill));
}

void SvgPolyline::setPoints(const std::vector<Point>& locs)
{
    auto points = std::make_unique<XmlAttribute>("points");

    std::stringstream sstr;
    for (const auto& loc : locs)
    {
        sstr << loc.getX() << "," << loc.getY() << " ";
    }
    points->setValue(sstr.str());
    addAttribute(std::move(points));
}

void SvgPolyline::setPoints(const Point& startPoint, const std::vector<Point>& locs)
{
    auto points = std::make_unique<XmlAttribute>("points");

    std::stringstream sstr;
    sstr << startPoint.getX() << "," << startPoint.getY() << " ";

    for (const auto& loc : locs)
    {
        sstr << loc.getX() << "," << loc.getY() << " ";
    }
    points->setValue(sstr.str());
    addAttribute(std::move(points));
}

SvgLine::SvgLine(const Point& startPoint, const Point& endPoint, std::size_t precision)
    : SvgShapeElement("line", precision)
{
    auto fill = std::make_unique<XmlAttribute>("fill");
    fill->setValue("none");
    addAttribute(std::move(fill));

    auto x1 = std::make_unique<XmlAttribute>("x1");
    x1->setValue(PointParser::toString(startPoint.getX(), mPrecision));
    addAttribute(std::move(x1));

    auto y1 = std::make_unique<XmlAttribute>("y1");
    y1->setValue(PointParser::toString(startPoint.getY(), mPrecision));
    addAttribute(std::move(y1));

    auto x2 = std::make_unique<XmlAttribute>("x2");
    x2->setValue(PointParser::toString(endPoint.getX(), mPrecision));
    addAttribute(std::move(x2));

    auto y2 = std::make_unique<XmlAttribute>("y2");
    y2->setValue(PointParser::toString(endPoint.getY(), mPrecision));
    addAttribute(std::move(y2));
}


SvgPath::SvgPath()
    : SvgShapeElement("path")
{

}

std::string SvgPath::getPath() const
{
    std::string d;
    if (auto attr = getAttribute("d"); attr)
    {
        d = attr->getValue();
    }
    return d;
}

void SvgPath::setPath(const std::string& mPath)
{
    auto path = std::make_unique<XmlAttribute>("d");
    path->setValue(mPath);
    addAttribute(std::move(path));
}

void SvgPath::setFillRule(const std::string& fillRule)
{
    auto rule = std::make_unique<XmlAttribute>("fill-rule");
    rule->setValue(fillRule);
    addAttribute(std::move(rule));
}
