// ------------------------------------------------------------------------
/*
	\author: Jaap Suter
   
	Copyright (C) Electronic Arts Canada Inc. 2002.  All rights reserved.	
*/
// ------------------------------------------------------------------------

/*! \file */

#ifndef REVEAL_RENDERER_H
#define REVEAL_RENDERER_H

#include "reveal/impl/gui_metrics.h"
#include "reveal/stdint.h"

namespace Reveal {

// ------------------------------------------------------------------------------
/*!
	\brief Abstract base class for the renderer

	This class interface needs to be implemented by Reveal clients.
*/
// ------------------------------------------------------------------------------
class Renderer
{	
public:

	//! Virtual destructor;
	virtual ~Renderer();
	
	/*!
		\brief Draws a line on the screen
		\param x1, y1 Start point of the line in GUI space;
		\param x2, y2 End point of the line in GUI space;
		\param color  ARGB color of the line;
	*/ 
	void Line( int x1, int y1, int x2, int y2, Reveal::uint32_t color ) const;
    
	/*!
		\brief Draws a bar (filled rectangle) on the screen
		\param x1, y1 Top left corner of the bar in GUI space;
		\param width, height Width and height of the bar;
		\param color ARGB color of the line;
	*/ 
	void Bar( int x1, int y1, int width, int height, Reveal::uint32_t color ) const;

	/*!
		\brief Draws some text on the screen
		\param x1, y1 Top left corner where the text is put in GUI space;
		\param str	  Const character array containing the text;
		\param color  ARGB color of the line;
	*/ 		
    void String( int x1, int y1, const char* str, Reveal::uint32_t color ) const;
	
	/*!
		\brief Draws a traingle on the screen
		\param x1, y1 First vertex of the triangle;
		\param x2, y2 Second vertex of the triangle;
		\param x3, y3 Third vertex of the triangle;
		\param color  ARGB color of the line;
	*/ 		
	void Triangle( int x1, int y1, int x2, int y2, int x3, int y3, Reveal::uint32_t color ) const;

	/*!
		\brief Converts the given coordinate from GUI space to screen space
		\param x GUI space x coordinate;
		\param y GUI space y coordinate;
		\return x Screen space x coordinate;
		\return y Screen space y coordinate;
	*/
	void ConvertFromGuiSpaceToScreenSpace( int &x, int &y ) const;

	/*!
		\brief This function tries to convert a gui-space coordinate to a worldspace coordinate;
		\param guiX guispace x coordinate;
		\param guiY guispace y coordinate;
		
		\retval worldX worldspace x coordinate;
		\retval worldY worldspace y coordinate;
		\retval worldZ worldspace z coordinate;

		\retval rayX worldspace x ray direction;
		\retval rayY worldspace y ray direction;
		\retval rayZ worldspace z ray direction;
		
		\return true if the function succeeded, false otherwise;
	*/
	bool ScreenSpaceToWorldSpace( int /*guiX*/, int  /*guiY*/, 
								  float&  /*worldspaceX*/, float&  /*worldspaceY*/, float& /*worldspaceZ*/,
								  float&  /*rayX*/, float&  /*rayY*/, float& /*rayZ*/ ) const;
	

	/*!
		\brief Must be implemented by the derived class. 

		This function should return the screen space X of the top left corner of the screen.
		Very often this will simply be zero, however on Television/Console combinations with
		overscan, this might be something like 35 or whatever.
	*/
	virtual int DoGetScreenOriginX() const = 0;

	//! See DoGetScreenOriginX() but then for Y instead.
	virtual int DoGetScreenOriginY() const = 0;

	/*!
		\brief Must be implemented by the derived class. 

		This function should return the screen space width of the screen.
		Very often this will simply be the resolution-width, however on Television/Console combinations with
		overscan, this might be something less because the right of the screen falls away the television.
	*/	
	virtual int DoGetScreenWidth() const = 0;

	//! See DoGetScreenWidth(), but then for the height instead;
    virtual int DoGetScreenHeight()  const = 0;

public:

	/*! 
		\brief Must be implemented by the derived class;

		This function should draw a line. The input coordinates are in screenspace, and the color
		is an 32 ARGB value. The coordinates are \a not clipped, so make sure your implementation supports off-screen
		coordinates.
	*/
    virtual void DoLine( int x1, int y1, int x2, int y2, Reveal::uint32_t color ) const = 0;
    
	/*! 
		\brief Must be implemented by the derived class;

		This function should draw a bar (filled rectangle). The input coordinates are in screenspace, and the color
		is an 32 ARGB value. The coordinates are \a not clipped, so make sure your implementation supports off-screen
		coordinates.
	*/
	virtual void DoBar( int x1, int y1, int width, int height, Reveal::uint32_t color ) const = 0;
    
	/*! 
		\brief Must be implemented by the derived class;

		This function should draw some text. The input coordinates are in screenspace, and the color
		is an 32 ARGB value. The coordinates are \a not clipped, so make sure your implementation supports off-screen
		coordinates.

		I don't care about what font you use, just make sure the size works well with the hardcoded GUI implementation.
		Any debug font that is readable on a television should do.

		If using a text window, be sure to set GuiMetrics::TEXT_HEIGHT and GuiMetrics::CHAR_WIDTH appropriately
	*/
	virtual void DoString( int x1, int y1, const char* str, Reveal::uint32_t color ) const = 0;
	
	/*! 
		\brief Must be implemented by the derived class;

		This function should draw a triangle. The input coordinates are in screenspace, and the color
		is an 32 ARGB value. The coordinates are \a not clipped, so make sure your implementation supports off-screen
		coordinates.
	*/
	virtual void DoTriangle( int x1, int y1, int x2, int y2, int x3, int y3, Reveal::uint32_t color ) const = 0;

	/*!
		\brief This function should convert a screen space coordinate to a worldspace ray;
		\param screenX screenspace x coordinate;
		\param screenY screenspace y coordinate;
		
		\retval worldX worldspace x coordinate;
		\retval worldY worldspace y coordinate;
		\retval worldZ worldspace z coordinate;

		\retval rayX worldspace x ray direction;
		\retval rayY worldspace y ray direction;
		\retval rayZ worldspace z ray direction;
		
		\return true if the function succeeded, false otherwise;

		You don't have to implement this function per se;
	*/
	virtual bool DoScreenSpaceToWorldSpace( int /*screenX*/, int  /*screenY*/, 
											float&  /*worldspaceX*/, float&  /*worldspaceY*/, float& /*worldspaceZ*/,
											float&  /*rayX*/, float&  /*rayY*/, float& /*rayZ*/ ) const { return false; }
};


} // Namespace Reveal;

#endif
