
#include <Spectre/Math/Vector4.h>
#include <Spectre/Graphics/Renderer2D.h>
#include <Spectre/Graphics/Text.h>

Text::Text() :
m_font		(NULL),
m_size		(22),
m_color		(255, 255, 255, 255),
m_outlineColor	(0, 0, 0, 255),
m_outlineWidth	(0)
{
}

Text::Text(const std::string text, unsigned int size, const Font& font) :
m_font			(&font),
m_size			(size),
m_string		(text),
m_color			(255, 255, 255, 255),
m_outlineColor		(0, 0, 0, 255),
m_outlineWidth		(0),
m_geometryNeedsUpdate	(true)
{
}

void Text::setString(const std::string& string)
{
	m_string = string;
	m_geometryNeedsUpdate = true;
}

const std::string& Text::getString() const
{
	return m_string;
}

void Text::setCharacterSize(unsigned int size)
{
	m_size = size;
	m_geometryNeedsUpdate = true;
}

unsigned int Text::getCharacteSize() const
{
	return m_size;
}

void Text::setFont(const Font& font)
{
	m_font = &font;
	m_geometryNeedsUpdate = true;
}
const Font* Text::getFont() const
{
	return m_font;
}

void Text::setColor(const Color& color)
{
	m_color = color;
	m_geometryNeedsUpdate = true;
}

const Color& Text::getColor() const
{
	return m_color;
}

void Text::setOutlineColor(const Color& color)
{
	m_outlineColor = color;
}

const Color& Text::getOutlineColor() const
{
	return m_outlineColor;
}

void Text::setOutlineSize(unsigned int size)
{
	m_outlineWidth = size;
}

unsigned int Text::getOutlineSize() const
{
	return m_outlineWidth;
}

Vector2f Text::getSize() const
{
	Vector2f size;

	for(size_t i = 0; i < m_string.size(); i++) {

		Font::Glyph glyph = m_font->getGlyph(m_string[i]);

		float h = glyph.size.y;
		float w = glyph.advance;

		if (h > size.y) {
			size.y = h;
		}
		size.x += w;
	}
	return size;
}

const Texture* Text::getTexture() const
{
	if (m_geometryNeedsUpdate) {
		updateGeometry();
		m_geometryNeedsUpdate = false;
	}
	return m_font->getTexture();
}

const std::vector<unsigned short>& Text::getIndices() const
{
	return m_indicies;
}

const std::vector<Vertex2D>& Text::getVertices() const
{
	if (m_geometryNeedsUpdate) {
		updateGeometry();
		m_geometryNeedsUpdate = false;
	}
	return m_vertices;
}

void Text::updateGeometry() const
{
	Vector2f origin;
	Vector2f size = getSize();
	Vector4f color = getColor().toRGBAf();

	m_vertices.clear();

	for(size_t i = 0; i < m_string.length(); i++) {

		Vertex2D v1, v2, v3, v4;

		Font::Glyph glyph = m_font->getGlyph(m_string[i]);

		if (glyph.texture) {

			Vector2f vpos = origin + vec2f(glyph.offset.x, size.y - glyph.offset.y);

			Vertex2D v1 = Vertex2D(vpos + vec2f(		0.0f,	0.0f),		vec2f(glyph.texture_origin.x, glyph.texture_origin.y));
			Vertex2D v2 = Vertex2D(vpos + vec2f(	glyph.size.x,	0.0f),		vec2f(glyph.texture_origin.x + glyph.size.x, glyph.texture_origin.y));
			Vertex2D v3 = Vertex2D(vpos + vec2f(	glyph.size.x,	glyph.size.y),	vec2f(glyph.texture_origin.x + glyph.size.x, glyph.texture_origin.y + glyph.size.y));
			Vertex2D v4 = Vertex2D(vpos + vec2f(		0.0f,	glyph.size.y),	vec2f(glyph.texture_origin.x, glyph.texture_origin.y + glyph.size.y));

			v1.color = color;
			v2.color = color;
			v3.color = color;
			v4.color = color;

			m_vertices.push_back(v1);
			m_vertices.push_back(v2);
			m_vertices.push_back(v3);
			m_vertices.push_back(v4);
		}

		origin.x += glyph.advance;
	}

	int x = 0;


}

void Text::render(Renderer2D& renderer) const
{
	renderer.draw(this);
}