#ifndef TEXTURE_CODE_H
#define TEXTURE_CODE_H

#include "texture.h"

namespace CBK
{
	template<int NumberTextureStages>
	_Texture<NumberTextureStages>* _Texture<NumberTextureStages>::currentTexture[NumberTextureStages] = {0};

	template<int NumberTextureStages>
	unsigned long _Texture<NumberTextureStages>::numTextureChanges;

	template<int NumberTextureStages>
	_Texture<NumberTextureStages>::_Texture(const std::string& name, IDirect3DDevice9* device) : Object(device)
	{
		texture = 0;

		magFilter = D3DTEXF_LINEAR;
		minFilter = D3DTEXF_LINEAR;
		mipFilter = D3DTEXF_LINEAR;

		load(name);
	}

	template<int NumberTextureStages>
	_Texture<NumberTextureStages>::~_Texture(void)
	{
		d3d::Release<IDirect3DTexture9*>(texture);
	}

	template<int NumberTextureStages>
	Object& _Texture<NumberTextureStages>::reset(void)
	{
		load(getName());
		return *this;
	}

	template<int NumberTextureStages>
	_Texture<NumberTextureStages>& _Texture<NumberTextureStages>::load(const std::string& name)
	{
		if (device == 0) return *this;

		if (texture != 0)
			d3d::Release<IDirect3DTexture9*>(texture);

		if (name != "")
			D3DXCreateTextureFromFile(device, name.c_str(), &texture);
		else
			texture = 0;

		setName(name);
		return *this;
	}

	template<int NumberTextureStages>
	_Texture<NumberTextureStages>& _Texture<NumberTextureStages>::setMipMapping(const DWORD& magFilter, const DWORD& minFilter, const DWORD& mipFilter)
	{
		this->magFilter = magFilter;
		this->minFilter = minFilter;
		this->mipFilter = mipFilter;

		return *this;
	}

	template<int NumberTextureStages>
	void _Texture<NumberTextureStages>::apply(const DWORD& stage)
	{
		if (device == 0) return;
		if (stage > NumberTextureStages) return;

		if (currentTexture[stage] != this)
		{
			device->SetSamplerState(stage, D3DSAMP_MAGFILTER, magFilter);
			device->SetSamplerState(stage, D3DSAMP_MINFILTER, minFilter);
			device->SetSamplerState(stage, D3DSAMP_MIPFILTER, mipFilter);
			device->SetTexture(stage, texture);
			currentTexture[stage] = this;
			numTextureChanges++;
		}
	}

	template<int NumberTextureStages>
	inline void _Texture<NumberTextureStages>::apply(void)
	{
		apply(0);
	}

	template<int NumberTextureStages>
	IDirect3DTexture9* _Texture<NumberTextureStages>::getTexture(void) const
	{
		return texture;
	}

	template<int NumberTextureStages>
	void _Texture<NumberTextureStages>::clear(IDirect3DDevice9* device, const DWORD& stage)
	{
		if (device == 0) return;
		if (stage > NumberTextureStages) return;

		if (currentTexture[stage] != 0)
		{
			device->SetTexture(0, 0);
			currentTexture[stage] = 0;
			numTextureChanges++;
		}
	}
}

#endif //TEXTURE_CODE_H