#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <UT/UT_Thread.h>
#include <UT/UT_String.h>
#include <VEX/VEX_VexOp.h>
#include "VexImageReader.h"
#include <math.h>
#include "VexImage.h"


namespace HDK_VexImageReader 
{

// The image handler used for loading and fetching images
VexImageHandler*	sImageHandler =	new VexImageHandler();



// Called before reading an image, keeps count of image references
void* HDK_VexImageReader::read_image_init()
{
	sImageHandler->mRefCounter++;
	return sImageHandler;
}



// Cleans images from memory if they're not needed anymore
void HDK_VexImageReader::read_image_cleanup(void* data)
{
	VexImageHandler* handler = (VexImageHandler*)data;

	handler->mRefCounter--;

	if(!handler->mRefCounter)
		handler->ClearImages();
}



// For a given image, sample to value at a specific location (u,v)
void HDK_VexImageReader::read_image_evaluate(int, void *argv[], void *data)
{
	// First get out input and output variables
	UT_Vector4* result = (UT_Vector4*)argv[0];		//< Will be used to store the result
	const float u = *((const float*)argv[1]);		//< U Sample Position
	const float v = *((const float*)argv[2]);		//< V Sample Position
	const int   m = *((const int*)argv[4]);			//< Sample Mode (0 = Wrap, > 0 = Streak)
	int*		success = (int*)argv[5];			//< Returns if the image was succesfully sampled

	// Set the sample to be not succesful
	*success = 0;

	// Get the name of our file
	const char* img_name = (const char*)argv[3];
	UT_String img_str = UT_String(img_name);

	// Get the image handler and retrieve the image to sample from
	VexImageHandler* handler= (VexImageHandler*)data;
	VexImage* image = handler->GetImage(img_str);
	if(!image->mInitialized)
	{
		*result = image->sErrorValue;
		return;
	}

	// If the image was initialized succesfully, return the color value at that specific uv location
	*result = image->GetColorValue(u, v, m, success);
}
}



// Installs the VEX function
using namespace HDK_VexImageReader;
void newVEXOp(void *)
{
	new VEX_VexOp("readimage@&PFFSI&I",
		read_image_evaluate,			// Function Evaluator
		VEX_ALL_CONTEXT,				// Applies to all VEX contexts
		read_image_init,				// Initializes the image reader
		read_image_cleanup,				// Cleans the image reader
		VEX_OPTIMIZE_1);				// Optimization Level
}