#ifndef Sampler_hpp
#define Sampler_hpp

#include "Color.hpp"

namespace swShader
{
	class Texture;
	class Rasterizer;
	class PixelPipeline;
	class PS_2_0Assembler;
	class VS_2_0Assembler;

	class Sampler
	{
		friend Rasterizer;
		friend PixelPipeline;
		friend PS_2_0Assembler;
		friend VS_2_0Assembler;

	public:
		enum FilterType
		{
			FILTER_POINT,
			FILTER_LINEAR,

			FILTER_LAST = FILTER_LINEAR
		};

		enum AddressingMode
		{
			ADDRESSING_WRAP,
			ADDRESSING_CLAMP,
			ADDRESSING_MIRROR,

			ADDRESSING_LAST = ADDRESSING_MIRROR
		};

		enum StageOperation
		{
			STAGE_DISABLE,
			STAGE_REPLACE,
			STAGE_SELECTARG1,
			STAGE_SELECTARG2,
			STAGE_SELECTARG3,
			STAGE_MODULATE,
			STAGE_MODULATE2X,
			STAGE_MODULATE4X,
			STAGE_ADD,
			STAGE_ADDSIGNED,
			STAGE_SUBTRACT,
			STAGE_MULTIPLYADD,
			STAGE_LERP,
			STAGE_DOT3,

			STAGE_LAST = STAGE_DOT3
		};

		enum SourceArgument
		{
			SOURCE_VOID,
			SOURCE_TEXTURE,
			SOURCE_CONSTANT,
			SOURCE_CURRENT,
			SOURCE_DIFFUSE,
			SOURCE_SPECULAR,
			SOURCE_TEMP,

			SOURCE_LAST = SOURCE_TEMP
		};

		enum DestinationArgument
		{
			DESTINATION_CURRENT,
			DESTINATION_TEMP,

			DESTINATION_LAST = DESTINATION_TEMP
		};

		enum ArgumentModifier
		{
			MODIFIER_COLOR,
			MODIFIER_INVCOLOR,
			MODIFIER_ALPHA,
			MODIFIER_INVALPHA,

			MODIFIER_LAST = MODIFIER_INVALPHA
		};

		Sampler();

		~Sampler();

		void init(int stage);

		void setTextureMap(Texture *texture);
		void releaseTexture();

		void setConstantColor(const Color<float> &constantColor);
		
		bool setTexCoordIndex(int texCoordIndex);
		bool setStageOperation(StageOperation stageOperation);
		bool setFirstArgument(SourceArgument firstArgument);
		bool setSecondArgument(SourceArgument secondArgument);
		bool setThirdArgument(SourceArgument thirdArgument);
		bool setFirstModifier(ArgumentModifier firstModifier);
		bool setSecondModifier(ArgumentModifier secondModifier);
		bool setThirdModifier(ArgumentModifier thirdModifier);
		bool setDestinationArgument(DestinationArgument destinationArgument);
		bool setTextureFilter(FilterType textureFilter);
		bool setAddressingMode(AddressingMode addressingMode);

		int status() const;

	private:
		Texture *texture;
		Color<short> constantColorShort;
		Color<float> constantColorFloat;

	//	Color<float> borderColor;
		FilterType textureFilter;
		AddressingMode addressingMode;
	//	MipmapFilter mipmapFilter;
	//	float mipmapBias;
	//	float gamma;

		// Fixed-function states
		StageOperation stageOperation;
		SourceArgument firstArgument;
		SourceArgument secondArgument;
		SourceArgument thirdArgument;
		ArgumentModifier firstModifier;
		ArgumentModifier secondModifier;
		ArgumentModifier thirdModifier;
		DestinationArgument destinationArgument;

		int texCoordIndex;
	};
}

#endif   // Sampler_hpp