#ifndef LIGHT_CODE_H
#define LIGHT_CODE_H

#include "light.h"

namespace CBK
{
	template<int NumberLightStages>
	_Light<NumberLightStages>* _Light<NumberLightStages>::_CurrentLight[NumberLightStages];

	template<int NumberLightStages>
	unsigned long _Light<NumberLightStages>::numLightChanges;

	template<int NumberLightStages>
	_Light<NumberLightStages>::_Light(IDirect3DDevice9* device) : Object(device)
	{
		::ZeroMemory(&_light, sizeof(_light));
		setType(D3DLIGHT_SPOT);
	}

	template<int NumberLightStages>
	_Light<NumberLightStages>::~_Light(void)
	{
	}

	template<int NumberLightStages>
	Object& _Light<NumberLightStages>::reset(void)
	{
		return *this;
	}

	template<int NumberLightStages>
	Object& _Light<NumberLightStages>::load(const std::string& name)
	{
		name;
		return *this;
	}

	template<int NumberLightStages>
	_Light<NumberLightStages>& _Light<NumberLightStages>::setColor(const D3DCOLORVALUE& ambient, const D3DCOLORVALUE& diffuse, const D3DCOLORVALUE& specular)
	{
		setColorAmbient(ambient);
		setColorDiffuse(diffuse);
		setColorSpecular(specular);

		return *this;
	}

	template<int NumberLightStages>
	_Light<NumberLightStages>& _Light<NumberLightStages>::setColorAmbient(const D3DCOLORVALUE& color)
	{
		_light.Ambient = color;

		return *this;
	}

	template<int NumberLightStages>
	_Light<NumberLightStages>& _Light<NumberLightStages>::setColorDiffuse(const D3DCOLORVALUE& color)
	{
		_light.Diffuse = color;

		return *this;
	}

	template<int NumberLightStages>
	_Light<NumberLightStages>& _Light<NumberLightStages>::setColorSpecular(const D3DCOLORVALUE& color)
	{
		_light.Specular = color;

		return *this;
	}

	template<int NumberLightStages>
	_Light<NumberLightStages>& _Light<NumberLightStages>::setType(const D3DLIGHTTYPE& type)
	{
		_light.Type = type;

		return *this;
	}

	template<int NumberLightStages>
	D3DLIGHTTYPE& _Light<NumberLightStages>::getType(void)
	{
		return _light.Type;
	}

	template<int NumberLightStages>
	void _Light<NumberLightStages>::apply(void)
	{
		apply(0);
	}

	template<int NumberLightStages>
	void _Light<NumberLightStages>::apply(const DWORD& index)
	{
		if (device == 0) return;
		if (index > NumberLightStages) return;

		if (_CurrentLight[index] != this)
		{
			device->SetLight(index, &_light);
			device->LightEnable(index, true);
			_CurrentLight[index] = this;
			numLightChanges++;
		}
	}

	template<int NumberLightStages>
	void _Light<NumberLightStages>::disable(IDirect3DDevice9* device, const DWORD& index)
	{
		if (device == 0) return;
		if (index > NumberLightStages) return;
		
		if (_CurrentLight[index] != 0)
		{
			device->LightEnable(index, false);
			_CurrentLight[index] = 0;
			numLightChanges++;
		}
	}

	template<int NumberLightStages>
	_Light<NumberLightStages>& _Light<NumberLightStages>::setCones(const float& theta, const float& phi, const float& falloff)
	{
		_light.Theta = theta;
		_light.Phi = phi;
		_light.Falloff = falloff;

		return *this;
	}

	template<int NumberLightStages>
	_Light<NumberLightStages>& _Light<NumberLightStages>::setAttenuation(const float& constant, const float& linear, const float& quadratic)
	{
		_light.Attenuation0 = constant;
		_light.Attenuation1 = linear;
		_light.Attenuation2 = quadratic;

		return *this;
	}

	template<int NumberLightStages>
	_Light<NumberLightStages>& _Light<NumberLightStages>::setFalloff(const float& falloff)
	{
		_light.Falloff = falloff;

		return *this;
	}

	template<int NumberLightStages>
	_Light<NumberLightStages>& _Light<NumberLightStages>::setPosition(const D3DVECTOR& position)
	{
		_light.Position = position;

		return *this;
	}

	template<int NumberLightStages>
	_Light<NumberLightStages>& _Light<NumberLightStages>::setDirection(const D3DVECTOR& direction)
	{
		_light.Direction = direction;

		return *this;
	}

	template<int NumberLightStages>
	const float& _Light<NumberLightStages>::getConeTheta(void)
	{
		return _light.Theta;
	}

	template<int NumberLightStages>
	const float& _Light<NumberLightStages>::getConePhi(void)
	{
		return _light.Phi;
	}

	template<int NumberLightStages>
	const float& _Light<NumberLightStages>::getConeFalloff(void)
	{
		return _light.Falloff;
	}

	template<int NumberLightStages>
	const float& _Light<NumberLightStages>::getAttenuationConstant(void)
	{
		return _light.Attenuation0;
	}

	template<int NumberLightStages>
	const float& _Light<NumberLightStages>::getAttenuationLinear(void)
	{
		return _light.Attenuation1;
	}

	template<int NumberLightStages>
	const float& _Light<NumberLightStages>::getAttenuationQuadratic(void)
	{
		return _light.Attenuation2;
	}

	template<int NumberLightStages>
	const float& _Light<NumberLightStages>::getFalloff(void)
	{
		return _light.Falloff;
	}

	template<int NumberLightStages>
	const D3DVECTOR& _Light<NumberLightStages>::getPosition(void)
	{
		return _light.Position;
	}

	template<int NumberLightStages>
	const D3DVECTOR& _Light<NumberLightStages>::getDirection(void)
	{
		return _light.Direction;
	}
}

#endif //LIGHT_CODE_H