//!
//! \file RayTracer.h
//! \brief Interface definition for the RayTracer class
//!
//! \author Austin McGee amcgee@digipen.edu
//! \date February 17, 2006
//!
//! Copyright 2006 DigiPen (USA) Corporation, all rights reserved.
//!
////////////////////////////////////////////////////////////////////////////////

#if !defined( __RAYTRACER_INCLUDED_20060217 )
#define __RAYTRACER_INCLUDED_20060217

#include <Windows.h>
#include "Object.h"
#include <vector>

struct Camera
{
	//Camera( void ) {}
	Camera( const Vector3 &cc, const Vector3 &uu, const Vector3 &vv, const Vector3 &ee )
	{ c = cc; u = uu; v = vv; e = ee; }

	Vector3 c;	// center of view plane
	Vector3 u;	// horizontal view vector
	Vector3 v;	// vertical view vector
	Vector3 e;	// eye of the camera
};

struct Light
{
	Light( const Vector3 &p, const Vector3 &rg, const float r )
	{ pos = p; rgb = rg; rad = r; }

	Vector3 pos;		// position of the light
	Vector3 rgb;		// color of the light
	float	rad;		// radiance of the light
};

class RayTracer
{

public:

	// constructors and destructor
	RayTracer( void );																		// default constructor
	~RayTracer( void );																		// default destructor

	// public functions
	void InitWindow( LRESULT CALLBACK DefaultWindowProc( HWND, UINT, WPARAM, LPARAM ) );	// initializes the window
	void SetFullscreen( bool value );														// sets whether the screen is fullscreen or not

	void Render( void );																	// render the scene
	void AddObject( Object *const obj ) { objectList_.push_back( obj ); }					// add an object to the scene
	void SetCamera( const Vector3 &c, const Vector3 &u, const Vector3 &v, const Vector3 &e );// set the camera's position and orientation
	void SetAmbient( const Vector3 &rgb ) { ambient_ = rgb; }								// set the ambient light
	void AddLight( Light light ) { lightList_.push_back( light ); }							// add a light to the scene

	HWND& GetWindow( void ) { return window_; }												// get a handle to the window
	void Clear( void );																		// clear the scene

	typedef std::vector<Object *> tObjectList;
	typedef std::vector<Light> tLightList;

protected:

	Vector3 GetLocalIllumination( const Vector3 &incident, const Vector3 &shadowInt, 
		const unsigned objHit, const Vector3 &normal, const float reflectCoeff );			// gets the local illumination for the ray cast
	float GetReflectionCoefficient( const float n, const float dot, const float square );	// gets the reflection coefficient for the ray cast
	Vector3 GetTransmissionVector( const Vector3 &incident, const Vector3 &normal, 
		const float n, const float dot, const float square );								// gets the transmission color
	Vector3 RayCast( const Ray &ray, int depth, float refraction );							// casts a ray into the world and gets the color
	float GetCollision( const Ray &ray, unsigned &objHit );									// gets the collision with the ray
	void CreateBackBuffer( void );															// creates the back buffer
	void SetPixel( const int x, const int y, const int color );								// sets a particular pixel on the screen

	// private variables
	WNDCLASS windowClass_;			// the window's class
	HWND window_;					// handle to the window
	wchar_t *className_;			// name of our class
	wchar_t *windowName_;			// name of the window
	int width_;						// width of the window
	int height_;					// height of the window
	DWORD style_;					// the style of our window
	bool fullscreen_;				// whether we're full screen or not
	bool redraw_;					// whether we need to redraw or not
	bool drawing_;					// whether we're drawing or not
	float iStep_;					// the step we're on for drawing
	int iWidth_;					// the width we're at for drawing
	static const int eWidth_ = 6;	// how much width to add for the window border
	static const int eHeight_ = 44;	// how much height to add for the window border/menu

	unsigned int *basePtr_;			// base pointer to back buffer
	HBITMAP backBitmap_;			// back buffer bitmap
	HBITMAP savedBitmap_;			// saved bitmap for god knows why (STUPID WINDOWS)
	HDC backBuffer_;				// actual back buffer

	Camera camera_;					// the camera for the scene
	Vector3 ambient_;				// the ambient light for the scene
	tObjectList objectList_;		// the list of objects
	tLightList lightList_;			// the list of lights
};

extern RayTracer *WINDOW;

#endif // __RAYTRACER_INCLUDED_20060217
