#include "Line.h"

#include "PointParser.h"

Line::Line(const Point& start, const PointCollection& points)
	:	mStartPoint(start),
		mPoints(points)
{

}

Line::Line(const Point& start, InputBufferType bufferType, const std::vector<double>& buffer)
	: mStartPoint(start)
{
	if (bufferType == InputBufferType::XY_REL)
	{
		for (std::size_t idx = 0; idx < buffer.size(); idx += 2)
		{
			const auto x = buffer[idx];
			const auto y = buffer[idx + 1];
			mPoints.addPoint(Point(mStartPoint.getX() + x, mStartPoint.getY() + y));
		}
	}
	else if (bufferType == InputBufferType::XY_ABS)
	{
		for (std::size_t idx = 0; idx < buffer.size(); idx += 2)
		{
			const auto x = buffer[idx];
			const auto y = buffer[idx + 1];
			mPoints.addPoint(Point(x, y));
		}
	}
	else if (bufferType == InputBufferType::HORIZONTAL_REL)
	{
		for (std::size_t idx = 0; idx < buffer.size(); idx ++)
		{
			const auto x = buffer[idx];
			mPoints.addPoint(Point(mStartPoint.getX() + x, mStartPoint.getY()));
		}
	}
	else if (bufferType == InputBufferType::HORIZONTAL_ABS)
	{
		for (std::size_t idx = 0; idx < buffer.size(); idx++)
		{
			const auto x = buffer[idx];
			mPoints.addPoint(Point(x, mStartPoint.getY()));
		}
	}
	else if (bufferType == InputBufferType::VERTICAL_REL)
	{
		for (std::size_t idx = 0; idx < buffer.size(); idx++)
		{
			const auto y = buffer[idx];
			mPoints.addPoint(Point(mStartPoint.getX(), mStartPoint.getY() + y));
		}
	}
	else if (bufferType == InputBufferType::VERTICAL_ABS)
	{
		for (std::size_t idx = 0; idx < buffer.size(); idx++)
		{
			const auto y = buffer[idx];
			mPoints.addPoint(Point(mStartPoint.getX(), y));
		}
	}
}

std::string Line::toPostScriptString(std::size_t precision) const
{
	if (mPostscriptPositioning == PostscriptPositioning::ABSOLUTE_TO)
	{
		std::string path = "L";
		for (const auto& point : mPoints.getPoints())
		{
			path += PointParser::toString(point, 2, " ", precision) + " ";
		}
		return path;
	}
	else
	{
		std::string path = "l";
		for (const auto& point : mPoints.getPoints())
		{
			path += PointParser::toStringRelative(point, mStartPoint, 2, " ", precision) + " ";
		}
		return path;
	}
}

Point Line::getFirstPoint() const
{
	return getLocation();
}

Point Line::getEndPoint() const
{
	return mPoints.getEndPoint();
}

const PointCollection& Line::getPoints() const
{
	return mPoints;
}

Line::Type Line::getType() const
{
	return Line::Type::LINE;
}

const Point& Line::getLocation() const
{
	return mStartPoint;
}

Bounds Line::getBounds() const
{
	auto bounds = mPoints.getBounds();
	bounds.includePoint(mStartPoint.getX(), mStartPoint.getY(), mStartPoint.getZ());
	return bounds;
}