#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], 15, "b%d", index);
			break;
		case CONSTANT_INTEGER_REGISTER:
			_snprintf(string[i], 15, "i%d", index);
			break;
		case COLOR_REGISTER:
			_snprintf(string[i], 15, "v%d", index);
			break;
		case CONSTANT_FLOAT_REGISTER:
			_snprintf(string[i], 15, "c%d", index);
			break;
		case INPUT_REGISTER:
			_snprintf(string[i], 15, "v%d", index);
			break;
		case INPUT_TEXTURE_COORDINATE_REGISTER:
			_snprintf(string[i], 15, "t%d", index);
			break;
		case LOOP_COUNTER_REGISTER:
			return "aL";
		case SAMPLER_REGISTER:
			_snprintf(string[i], 15, "s%d", index);
			break;
		case TEMPORARY_REGISTER:
			_snprintf(string[i], 15, "r%d", index);
			break;
		case DIFFUSE_SPECULAR_REGISTER:
			_snprintf(string[i], 15, "oD%d", index);
			break;
		case POSITION_REGISTER:
			_snprintf(string[i], 15, "oPos%d", index);
			break;
		case POINT_SIZE_REGISTER:
			return "oPts";
		case TEXTURE_COORDINATE_REGISTER:
			_snprintf(string[i], 15, "oT%d", index);
			break;
		case FOG_REGISTER:
			return "oFog";
		case OUTPUT_COLOR_REGISTER:
			_snprintf(string[i], 15, "oC%d", index);
			break;
		case OUTPUT_DEPTH_REGISTER:
			return "oDepth";
		case CONSTANT_FLOAT_LITERAL:
			_snprintf(string[i], 15, "%f", value);
			break;
		case INTERNAL_REGISTER:
			_snprintf(string[i], 15, "tmp%d", index);
			break;
		case INTERNAL_TRANSFORM:
			_snprintf(string[i], 15, "trans");
			break;
		case INTERNAL_LIGHT_POSITION:
			_snprintf(string[i], 15, "light%d", index);
			break;
		case INTERNAL_MATERIAL_SHININESS:
			_snprintf(string[i], 15, "pow");
			break;
		case INTERNAL_CAMERA_POSITION:
			_snprintf(string[i], 15, "cam");
			break;
		case INTERNAL_CONSTANT:
			_snprintf(string[i], 15, "const%d", index);
			break;
		case INTERNAL_AMBIENT_LIGHT:
			_snprintf(string[i], 15, "amb");
			break;
		case INTERNAL_MATERIAL_SPECULAR:
			_snprintf(string[i], 15, "spec");
			break;
		case INTERNAL_MATERIAL_DIFFUSE:
			_snprintf(string[i], 15, "diff");
			break;
		case INTERNAL_MATERIAL_EMISSION:
			_snprintf(string[i], 15, "emiss");
			break;
		case INTERNAL_MATERIAL_AMBIENT:
			_snprintf(string[i], 15, "mamb");
			break;
		case INTERNAL_LIGHT_COLOR:
			_snprintf(string[i], 15, "lcol%d", index);
			break;
		case INTERNAL_ATTENUATION_CONSTANT:
			_snprintf(string[i], 15, "att%dc", index);
			break;
		case INTERNAL_ATTENUATION_LINEAR:
			_snprintf(string[i], 15, "att%dl", index);
			break;
		case INTERNAL_ATTENUATION_QUADRATIC:
			_snprintf(string[i], 15, "att%dq", index);
			break;
		case INTERNAL_LIGHT_RANGE:
			_snprintf(string[i], 15, "range%d", index);
			break;
		default:
			throw INTERNAL_ERROR;
		}

		if(sel != xyzwMask)
		{
			_snprintf(string[i], 15, "%s.", string[i]);

			switch(sel.x)
			{
			case X:	_snprintf(string[i], 15, "%sx", string[i]);	break;
			case Y:	_snprintf(string[i], 15, "%sy", string[i]);	break;
			case Z:	_snprintf(string[i], 15, "%sz", string[i]);	break;
			case W:	_snprintf(string[i], 15, "%sw", string[i]);	break;
			}

			switch(sel.y)
			{
			case X:	_snprintf(string[i], 15, "%sx", string[i]);	break;
			case Y:	_snprintf(string[i], 15, "%sy", string[i]);	break;
			case Z:	_snprintf(string[i], 15, "%sz", string[i]);	break;
			case W:	_snprintf(string[i], 15, "%sw", string[i]);	break;
			}

			switch(sel.z)
			{
			case X:	_snprintf(string[i], 15, "%sx", string[i]);	break;
			case Y:	_snprintf(string[i], 15, "%sy", string[i]);	break;
			case Z:	_snprintf(string[i], 15, "%sz", string[i]);	break;
			case W:	_snprintf(string[i], 15, "%sw", string[i]);	break;
			}

			switch(sel.w)
			{
			case X:	_snprintf(string[i], 15, "%sx", string[i]);	break;
			case Y:	_snprintf(string[i], 15, "%sy", string[i]);	break;
			case Z:	_snprintf(string[i], 15, "%sz", string[i]);	break;
			case W:	_snprintf(string[i], 15, "%sw", string[i]);	break;
			}
		}

		return string[i];
	}
}