#ifndef __SHADERENVIRONMENT_H__
#define __SHADERENVIRONMENT_H__

#include "tuple.h"
#include "color.h"
#include "transform.h"
#include "refcountedlist.h"
#include "geometryset.h"

namespace xrt
{
	class Scene;
	class RayDifferential;
	class Light;

	class RayInfo
	{
	public:
		enum Type { CAMERA, SPECULAR, TRANSMISSION };
		Tuple direction;
		Tuple origin;
		Type type;
		float depth;
	};

	class PUBLIC ShaderEnvironment
	{
	public:
		float ncomps;
		float alpha;
		Color Ci, Cs, Cl;
		Color Oi, Os, Ol;
		float u, v, du, dv, s, t;
		float ug, vg;
		Tuple P, Ps;
		Tuple N, Ng;
		Tuple I, L;
		Tuple E;
		Tuple dPdu, dPdv, dNdu, dNdv;
		Tuple dPdx, dPdy;
		float dudx, dudy, dvdx, dvdy;
		float time;
		float distance;
		GeometrySet* geometrySet;
		Reference< RefCountedList< Reference< Light > > > activeLights;
		RayInfo ray;
		const Scene *scene; //backdoor to renderer context
		Transform worldToObject;
		Transform worldToShader;
		std::vector<float> scratch;
		unsigned int highestScratch;
		unsigned int whichDifferential;
		struct Lighting
		{
			Lighting( Tuple L, Color Cl, Color Ol, Light* light ): L(L), Cl(Cl), Ol(Ol), light(light) {}
			Tuple L;
			Color Cl, Ol;
			Light* light;
		};
		std::vector< Lighting > illuminanceCache;
		Light* currentLight;

		std::vector< Reference< Light > >::iterator lightIte;
		std::vector< ShaderEnvironment::Lighting >::iterator cacheIterator;
		unsigned int totalSamples;
		Tuple position;
		Tuple axis;
		float angle;
		bool isIlluminanceCacheValid;
		void computeDifferentials( const RayDifferential& );
		ShaderEnvironment();
		ShaderEnvironment& operator= ( const ShaderEnvironment& sv );
	};
}
#endif //__SHADERENVIRONMENT_H__
