/****************************************************************************************/
/*  JESHADER.C                                                                          */
/*                                                                                      */
/*  Author: Timothy Roff	                                                            */
/*  Description:  Shader implementation                                                 */
/*                                                                                      */
/*  The contents of this file are subject to the Jet3D Public License                   */
/*  Version 1.02 (the "License"); you may not use this file except in                   */
/*  compliance with the License. You may obtain a copy of the License at                */
/*  http://www.jet3d.com                                                                */
/*                                                                                      */
/*  Software distributed under the License is distributed on an "AS IS"                 */
/*  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See                */
/*  the License for the specific language governing rights and limitations              */
/*  under the License.                                                                  */
/*                                                                                      */
/*  This file was not part of the original Jet3D, released December 12, 1999.           */
/*                                                                                      */
/****************************************************************************************/

#include "jeShaderDefs.h"
#include "jeShader.h"
#include "jeChain.h"
#include "Errorlog.h"
#include "jeAssert.h"

void jeShader_Error(const char * error, ...);
void WriteInfo(shader_info_t *info, char* name);

JETAPI jeBoolean jeWorld_AddShader(jeWorld *World, jeShader *Shader);

JETAPI jeBoolean JETCC jeShader_Destroy(jeShader **ptrShader)
{
	//destroys a shader
	jeShader	* shader;

	assert(ptrShader != NULL);

	shader = *ptrShader;

	if ( shader ) //check 1
	{
		if(shader->userdata->shader_vars.proceng.hasProc) //check 1.1
		{
			if(shader->userdata->shader_vars.proceng.initialized == 1) //check 1.1.2
			{
				shader->userdata->shader_vars.proceng.Destroy(shader->userdata->shader_vars.proceng.P);
				shader->userdata->shader_vars.proceng.initialized = 0;
				shader->userdata->shader_vars.proceng.hasProc = JE_FALSE;
			}
		}

		jeRam_Free(shader->userdata); //the user data has RAM alloced to it, so free it first
		jeRam_Free(shader); //free the shader

		return JE_TRUE;

	}

	return JE_FALSE;
}

JETAPI jeShader * jeShader_Create()
{
	//create a shader
	shader_info_t	*data;
	jeShader		*shader;
	int i;
	
	data = JE_RAM_ALLOCATE_STRUCT(shader_info_t);
	memset(data, 0, sizeof(shader_info_t));

	shader = JE_RAM_ALLOCATE_STRUCT(jeShader);
	memset(shader, 0, sizeof(jeShader));

	#ifdef _DEBUG
	jeShader_Error("setting temp_info settings");
	#endif
	
	shader->TimeAlpha = 0.0f;

	data->shader_vars.actor_var = "<NONE>";
	
	for(i = 0; i < JE_SHADER_MAX_ANIMAP; i++)
	{
		data->shader_vars.texture_maps[i] = "<NONE>";
	}

	data->shader_file = NULL;
	data->lookahead = JE_SHADER_TOKEN_EOF;
	data->jet_shader_line_count = 1;
	data->brace_count = 0;
	data->next_line_count = 1;
	data->uninputted = JE_FALSE;
	data->uninput_cin = '\0';
	
	data->shader_vars.proceng.hasProc = JE_FALSE;
	data->shader_vars.proceng.type_flags = PROC_NONE;
	data->shader_vars.proceng.initialized = 0;
	data->shader_vars.proceng.proc_name = "<NONE>";
	
	shader->userdata = data; //set shader->userdata to data
	sprintf(shader->tag, "SHDR");
	
	return(shader);

}

JETAPI jeShader * jeShader_CreateFromFile(char * script, char * refname)
{
	FILE*		file;
	jeShader	*my_shader;

	assert(script != NULL);

	file = fopen(script, "r");

	if (!file)
	{
		jeErrorLog_AddString(JE_ERR_SUBSYSTEM_FAILURE, "jeShader_CreateFromFile: could not open the script file! ", script);
		return JE_FALSE;
	}

	my_shader = jeShader_Create();
	my_shader->userdata->shader_file = file;

	jeShader_SetInput(file, my_shader->userdata);
	jeShader_Parse(NULL, NULL, my_shader->userdata); // retreive vars

	#ifdef _DEBUG
	WriteInfo(my_shader->userdata, refname);
	#endif

	return(my_shader);
}


JETAPI void jeShader_InteractiveParse() //TODO write me!!!!
{	
	jeShader_Parse(NULL, NULL, NULL); //TODO WRITE COMPILER FOR ARG 0!!!
}

JETAPI jeBoolean jeShader_Run(char * script, jeWorld *World)
{
	FILE* f;
	jeShader	*my_shader;
		
	assert(script != NULL); //some checking

	
	#ifdef _DEBUG
	jeShader_Error("opening script");
	#endif
	
	f = fopen(script, "r"); //open the script for reading

	if (!f)
	{
		jeErrorLog_AddString(JE_ERR_SUBSYSTEM_FAILURE, "ScriptRun: could not open the script file! ", script);
		return JE_FALSE;
	}

	//create the shader file
	my_shader = jeShader_Create();

	//set the script file
	my_shader->userdata->shader_file = f;

	//everything is good so parse the script
	#ifdef _DEBUG
	jeShader_Error("entering jeShader_SetInput");
	#endif
	
	jeShader_SetInput(f, my_shader->userdata);

	#ifdef _DEBUG
	jeShader_Error("Here goes nothing... entering jeShader_Parse...");
	#endif

	jeShader_Parse(NULL, NULL, my_shader->userdata);

	#ifdef _DEBUG
	jeShader_Error("Done with Parse!!! Adding shader to World->ShaderChain");
	#endif

	// The shader was parsed successfully
	// and the internal variables where assigned correctly
	// so add the shader to the World->ShaderChain so it
	// gets processed by jeWorld_RenderALL

	jeWorld_AddShader(World, my_shader);

	#ifdef _DEBUG
	WriteInfo(my_shader->userdata, "manual_run");
	#endif

	//jeRam_Free(temp_info); Not needed anymore; shader is destroyed by World now

	return JE_TRUE;
}

void WriteInfo(shader_info_t *info, char* name)
{
	FILE		*f;
	char		temp[255];
	
	sprintf(temp, "shader_vars_-_%s.txt", name);
	
	f = fopen(temp, "wt");

	if (f)
	{
		int i;
		int count;

		count = info->shader_vars.used_maps;

		for(i = 0; i < count; i++)
		{
			fprintf(f, "map: %s\n", info->shader_vars.texture_maps[i]);
		}

		fprintf(f, "actor: %s\n", info->shader_vars.actor_var);
		fprintf(f, "particle: %i, %i\n", info->shader_vars.particle_system.particle_origin, info->shader_vars.particle_system.particle_type);
		if(info->shader_vars.shader_type_flags == TYPE_SHADER)
			fprintf(f, "type: shader\n");
		if(info->shader_vars.shader_type_flags == TYPE_MP3SCRIPT)
			fprintf(f, "type: mp3 scriptlet\n");
		if(info->shader_vars.shader_type_flags == (TYPE_HYBRID | TYPE_SHADER | TYPE_MP3SCRIPT | TYPE_EXTENSION))
			fprintf(f, "type: shader and mp3 hybrid extention\n");
		if(info->shader_vars.shader_type_flags == TYPE_EXTENSION)
			fprintf(f, "type: extension\n");
		if(info->shader_vars.shader_type_flags == (TYPE_UNKNOWN | TYPE_EXTENSION))
			fprintf(f, "type: unknown\n");

	}
	
}