//	TextLayout.h - Class which lays out a string of text for a given font.
//  ----------------------------------------------------------------------------
//	This file is part of 'NiallsAVLib', base code for any kind of audiovisual
//	apps.
//	Copyright (C) 2012  Niall Moody
//	
//	This program is free software: you can redistribute it and/or modify
//	it under the terms of the GNU General Public License as published by
//	the Free Software Foundation, either version 3 of the License, or
//	(at your option) any later version.
//
//	This program is distributed in the hope that it will be useful,
//	but WITHOUT ANY WARRANTY; without even the implied warranty of
//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//	GNU General Public License for more details.
//
//	You should have received a copy of the GNU General Public License
//	along with this program.  If not, see <http://www.gnu.org/licenses/>.
//	----------------------------------------------------------------------------

#ifndef TEXTLAYOUT_H_
#define TEXTLAYOUT_H_

#include "FontMetrics.h"
#include "TwoFloats.h"

#include <vector>

///	Class which lays out a string of text for a given font.
class TextLayout
{
  public:
	///	Constructor.
	TextLayout();
	///	Destructor.
	~TextLayout();

	///	Struct representing a single glyph position in the text.
	struct GlyphPos
	{
		///	The glyph's image.
		std::wstring image;
		///	The glyph's position.
		TwoFloats position;
		///	The glyph's width/advance.
		float width;
		///	The glyph's character.
		wchar_t character;
	};
	///	Enum representing the three justification types.
	enum Justification
	{
		Left,
		Centre,
		Right
	};
	///	A callback used to load glyphs which are missing from a FontMetrics passed to getLayoutForText().
	class MissingGlyphCallback
	{
	  public:
		///	Destructor.
		virtual ~MissingGlyphCallback() {};

		///	Called when getLayoutForText() encounters a glyph that has not been loaded.
		/*!
			\param missingCharacter The character that is missing from our
			FontMetrics.
			\param metrics The FontMetrics to add the glyph to.
			\param fontId The identifier of the font we're using.

			\return An iterator pointing to the newly-loaded glyph in metrics.
		 */
		virtual FontMetrics::iterator loadMissingGlyph(wchar_t missingCharacter,
													   FontMetrics& metrics,
													   const std::wstring& fontId) = 0;
	};

	///	Lays out the text, returns a reference to a vector of the glyph positions.
	/*!
		\param text The string to layout. \n will trigger a new line.
		\param metrics The size etc. of all the glyphs in the font we're using.
		\param boxWidth The width of the box to layout the text in. Lines of
		text which extend beyond this will be truncated to the previous
		whitespace, with any text following it moved to the line below.
		\param scale The amount to scale the images by.
		\param Justification How the text should be justified.
		\param fontId Used by callback.
		\param callback Callback used to load glyphs missing from the passed-in
		FontMetrics.

		\return A vector containing the positions of all the glyphs required to
		draw the text. Note that this will only be valid for as long as the
		TextLayout instance is valid, so don't try using it once the TextLayout
		instance has been deleted/moved out of scope. The positions of the
		glyphs returned are relative to (0,0).
	 */
	const std::vector<GlyphPos>& getLayoutForText(const std::wstring& text,
												  FontMetrics& metrics,
												  float boxWidth,
												  float scale,
												  Justification justification,
												  const std::wstring& fontId,
												  MissingGlyphCallback *callback);
	///	Returns glyphPos without updating it.
	const std::vector<GlyphPos>& getExistingLayout() const {return glyphPos;};

	///	Clears glyphPos.
	void clear();
	///	Returns true if glyphPos is empty.
	bool getUninitialised() const {return !glyphPos.size();};
  private:
	///	Helper method. Adds a line of glyphs to glyphPos.
	void addLine(std::vector<GlyphPos>& glyphs,
				 float boxWidth,
				 float lineWidth,
				 Justification justification);

	///	Our vector of glyph positions.
	/*!
		This is what's returned from getLayoutForText().
	 */
	std::vector<GlyphPos> glyphPos;
};

#endif
