#ifndef PHONGSHADER_HXX
#define PHONGSHADER_HXX

#include "Shader.hxx"
 
class PhongShader : public Shader
{
public:
	Vec3f color;             // base color
	Vec3f ambient;           // ambient radiance 
	Vec3f light_ray_org_std; // template for light_ray.org, to calculate it only once
	float ka;                // ambient coefficient
	float kd;                // diffuse reflection coefficients
	float ks;                // specular refelection coefficients
	float ke;                // shininess exponent

	PhongShader(Scene *scene,
	            Vec3f color, float ka,float kd, float ks, float ke)
		: Shader(scene),color(color),ka(ka),kd(kd),ks(ks),ke(ke)
	{
		ambient = ka * Product(color, La);
	};

	virtual Vec3f Shade(Ray &ray)
	{
		Vec3f Lr(0,0,0),
		      Ll,
		      N = ray.hit->GetNormal(ray);
		Ray   light_ray;
		float intensity_scale;

		if (Dot(N,ray.dir) > 0)
			N = -N;

		light_ray_org_std = ray.org + ray.t * ray.dir;

		for (std::vector<Light*>::iterator it = scene->lights.begin(); it != scene->lights.end(); ++it)
		{
			light_ray.org  = light_ray_org_std;

#ifdef AREALIGHT
			for (int i = 0; i < NUM_AREA_SAMPLES; ++i)
#endif
			{
				(*it)->Illuminate(light_ray, Ll);

				if (!scene->Occluded(light_ray))
				{
					intensity_scale = Dot(light_ray.dir, N);

					if (intensity_scale > 0)
						Lr += kd * Product(color, Ll) * intensity_scale 
						   +  ks * Product(cs, Ll)    * powf(Dot(light_ray.dir, ray.dir + 2 * Dot(ray.dir, -N) * N), ke);
				}
			}
		}

#ifdef AREALIGHT
		Lr /= NUM_AREA_SAMPLES;
#endif
		Lr += ambient;
		return Lr;
	};
};

#endif
