#include "LineSegment.h"

#include "PointParser.h"

LineSegment::LineSegment(const Point&  p0, const Point& p1)
    : mP0(p0),
      mP1(p1)
{

}

std::unique_ptr<LineSegment> LineSegment::Create(const Point&  p0, const Point& p1)
{
    return std::make_unique<LineSegment>(p0, p1);
}

double LineSegment::getLength() const
{
    return mP0.getDistance(mP1);
}

const Point& LineSegment::getPoint0() const
{
    return mP0;
}

const Point& LineSegment::getPoint1() const
{
    return mP1;
}

void LineSegment::sample(SparseGrid<bool>*) const
{

}

std::string LineSegment::toPostScriptString(std::size_t precision) const
{
	if (isHorizontal())
	{
		if (mPostscriptPositioning == PostscriptPositioning::ABSOLUTE_TO)
		{
			return "H" + PointParser::toString(mP1.getX(), precision);
		}
		else
		{
			return "h" + PointParser::toString(mP0.getDeltaX(mP1), precision);
		}
	}
	else if (isVertical())
	{
		if (mPostscriptPositioning == PostscriptPositioning::ABSOLUTE_TO)
		{
			return "V" + PointParser::toString(mP1.getY(), precision);
		}
		else
		{
			return "v" + PointParser::toString(mP0.getDeltaY(mP1), precision);
		}
	}
	else
	{
		if (mPostscriptPositioning == PostscriptPositioning::ABSOLUTE_TO)
		{
			return "L" + PointParser::toString(mP1, 2, " ", precision);
		}
		else
		{
			return "l" + PointParser::toStringRelative(mP1, mP0, 2, " ", precision);
		}
	} 
}

bool LineSegment::isHorizontal() const
{
	return mP0.getDeltaY(mP1) == 0.0;
}

bool LineSegment::isVertical() const
{
	return mP0.getDeltaX(mP1) == 0.0;
}

Bounds LineSegment::getBounds() const
{
    const auto minX = std::min(mP0.getX(), mP1.getX());
    const auto maxX = std::max(mP0.getX(), mP1.getX());

    const auto minY = std::min(mP0.getY(), mP1.getY());
    const auto maxY = std::max(mP0.getY(), mP1.getY());

    return {minX, maxX, minY, maxY};
}

const Point& LineSegment::getLocation() const
{
    return mP0;
}

Point LineSegment::getFirstPoint() const
{
    return getPoint0();
}

Point LineSegment::getEndPoint() const
{
    return getPoint1();
}

LineSegment::Type LineSegment::getType() const
{
    return AbstractGeometricItem::Type::LINE_SEGMENT;
}
