#include "Operand.hpp"

#include "Error.hpp"

#include <stdio.h>

namespace swShader
{
	const char *Operand::string() const
	{
		// Dirty trick (non critical)
		static char string[16][16];
		static int n = 0;

		int i = n++ % 16;

		switch(type)
		{
		case VOID:
			return 0;
		case ADDRESS_REGISTER:
			return "a0";
		case CONSTANT_BOOLEAN_REGISTER:
			_snprintf(string[i], 255, "b%d", index);
			break;
		case CONSTANT_INTEGER_REGISTER:
			_snprintf(string[i], 255, "i%d", index);
			break;
		case COLOR_REGISTER:
			_snprintf(string[i], 255, "v%d", index);
			break;
		case CONSTANT_FLOAT_REGISTER:
			_snprintf(string[i], 255, "c%d", index);
			break;
		case INPUT_REGISTER:
			_snprintf(string[i], 255, "v%d", index);
			break;
		case INPUT_TEXTURE_COORDINATE_REGISTER:
			_snprintf(string[i], 255, "t%d", index);
			break;
		case LOOP_COUNTER_REGISTER:
			return "aL";
		case SAMPLER_REGISTER:
			_snprintf(string[i], 255, "s%d", index);
			break;
		case TEMPORARY_REGISTER:
			_snprintf(string[i], 255, "r%d", index);
			break;
		case DIFFUSE_SPECULAR_REGISTER:
			_snprintf(string[i], 255, "oD%d", index);
			break;
		case POSITION_REGISTER:
			_snprintf(string[i], 255, "oPos%d", index);
			break;
		case POINT_SIZE_REGISTER:
			return "oPts";
		case TEXTURE_COORDINATE_REGISTER:
			_snprintf(string[i], 255, "oT%d", index);
			break;
		case FOG_REGISTER:
			return "oFog";
		case OUTPUT_COLOR_REGISTER:
			_snprintf(string[i], 255, "oC%d", index);
			break;
		case OUTPUT_DEPTH_REGISTER:
			return "oDepth";
		case CONSTANT_FLOAT_LITERAL:
			_snprintf(string[i], 255, "%f", value);
			break;
		case INTERNAL_REGISTER:
			_snprintf(string[i], 255, "tmp%d", index);
			break;
		default:
			throw INTERNAL_ERROR;
		}

		if(sel != xyzwMask)
		{
			_snprintf(string[i], 255, "%s.", string[i]);

			switch(sel.x)
			{
			case X:	_snprintf(string[i], 255, "%sx", string[i]);	break;
			case Y:	_snprintf(string[i], 255, "%sy", string[i]);	break;
			case Z:	_snprintf(string[i], 255, "%sz", string[i]);	break;
			case W:	_snprintf(string[i], 255, "%sw", string[i]);	break;
			}

			switch(sel.y)
			{
			case X:	_snprintf(string[i], 255, "%sx", string[i]);	break;
			case Y:	_snprintf(string[i], 255, "%sy", string[i]);	break;
			case Z:	_snprintf(string[i], 255, "%sz", string[i]);	break;
			case W:	_snprintf(string[i], 255, "%sw", string[i]);	break;
			}

			switch(sel.z)
			{
			case X:	_snprintf(string[i], 255, "%sx", string[i]);	break;
			case Y:	_snprintf(string[i], 255, "%sy", string[i]);	break;
			case Z:	_snprintf(string[i], 255, "%sz", string[i]);	break;
			case W:	_snprintf(string[i], 255, "%sw", string[i]);	break;
			}

			switch(sel.w)
			{
			case X:	_snprintf(string[i], 255, "%sx", string[i]);	break;
			case Y:	_snprintf(string[i], 255, "%sy", string[i]);	break;
			case Z:	_snprintf(string[i], 255, "%sz", string[i]);	break;
			case W:	_snprintf(string[i], 255, "%sw", string[i]);	break;
			}
		}

		return string[i];
	}
}