/****************************************************************************************/
/*  REPORT.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.h"

void jeShader_WriteLog(const char *Msg);

void jeShader_FatalError(shader_info_t *info, const char * error, ...)
{
	va_list	ArgPtr;
	char	temp[500];

	va_start( ArgPtr, error);
	vsprintf(temp, error, ArgPtr);
	va_end(ArgPtr);

	jeErrorLog_Add(JE_ERR_SUBSYSTEM_FAILURE, "FATAL ERROR OCCURED");
	jeErrorLog_AddString(JE_ERR_SHADER_SCRIPT, "", temp);

	jeShader_WriteLog("Fatal Error: Shader cannot continune");

	jeShader_Parse_stop(info);

}


void jeShader_Error(const char * error, ...)
{
	va_list	ArgPtr;
	char	temp[500];

	va_start( ArgPtr, error);
	vsprintf(temp, error, ArgPtr);
	va_end(ArgPtr);

	jeErrorLog_AddString(JE_ERR_SHADER_SCRIPT, "", temp);

	#ifdef _DEBUG
	//we are in debug so write EVERYTHING from AddStrings to a log file
	jeShader_WriteLog(temp);
	#endif
}

void jeShader_WriteLog(const char *Msg)
{
	//very damn usefull for finding bugs (in code)

	va_list		ArgPtr;
    char		TempStr[500];
    char		TempStr2[500];
	FILE		*f;

	va_start (ArgPtr, Msg);
    vsprintf (TempStr, Msg, ArgPtr);
	va_end (ArgPtr);

	f = fopen("shader_log.txt", "wt");

	if (f)
	{
		int32		i, NumErrors;

		NumErrors = jeErrorLog_Count();

		fprintf(f, "Error#:%3i, Code#:%3i, Info: %s\n", NumErrors, 0, TempStr);

		for (i=0; i<NumErrors; i++)
		{
			jeErrorLog_ErrorClassType	Error;
			char						*String;

			if (jeErrorLog_Report(NumErrors-i-1, &Error, &String, &String))
			{
				fprintf(f, "Error#:%3i, Code#:%3i, Info:%s\n", NumErrors-i-1, Error, String);
			}
		}

		fclose(f);
		
	}
	else
	{
		sprintf(TempStr2, "%s\nCould NOT output to shader_log.txt", TempStr);
		MessageBox(0, TempStr2, "**ERROR**", MB_OK);
		_exit(1);
	}
	
}

//REWRITE ALL OF THE BELOW FUNCTIONS
//SO THAT THEY CAN 'REPORT' VALUE TO INTERNAL
//VARIABLES THAT ARE USED FOR ENGINE INTERGRATION

/*
void report_skyparms(shader_t* shader)
{
   if ((shader->flags & SH_FAR_BOX) ||
       (shader->flags & SH_SKYGEN)  ||
       (shader->flags & SH_NEAR_BOX)) {
      printf("\nskyparms:\n\n");

      printf("\tfar box basename: ");

      if (shader->flags & SH_FAR_BOX) {
         printf("%s\n", shader->far_box_basename);
      }
      else {
         printf("-\n");
      }

      if (shader->flags & SH_SKYGEN) {
         printf("\tcloudheight: %s\n", shader->cloud_height.string);
      }
      else {
         printf("no cloud layer\n");
      }

      printf("\tnear box basename: ");

      if (shader->flags & SH_NEAR_BOX) {
         printf("%s\n", info->shader->near_box_basename);
      }
      else {
         printf("-\n");
      }
   }
   else {
      printf("\nskyparms: <none>\n");
   }
}



 void report_cull(shader_t* shader)
{
   printf("\ncull: %s\n", sh_cull_to_string(shader->cull_face));
}



 void report_vxmod(sh_vxmod_t* vxmod)
{
   printf("%s\n", sh_vxmod_to_string(vxmod->func));

   switch(vxmod->func) {
      case SH_VXMOD_WAVE:
         printf("\n");
         printf("\t\tdiv:       %s\n", vxmod->args.wave.div.string);
         printf("\t\twaveform:  %s\n", sh_waveform_to_string(vxmod->args.wave.form));
         printf("\t\tbase:      %s\n", vxmod->args.wave.base.string);
         printf("\t\tamplitude: %s\n", vxmod->args.wave.amp.string);
         printf("\t\tphase:     %s\n", vxmod->args.wave.phase.string);
         printf("\t\tfrequency: %s\n", vxmod->args.wave.freq.string);
         break;

      case SH_VXMOD_NORMAL:
         printf("\n");
         printf("\t\tamplitude: %s\n", vxmod->args.normal.amp.string);
         printf("\t\tfrequency: %s\n", vxmod->args.normal.freq.string);
         break;

      case SH_VXMOD_BULGE:
         printf("\n");
         printf("\t\twidth:     %s\n", vxmod->args.bulge.width.string);
         printf("\t\theight:    %s\n", vxmod->args.bulge.height.string);
         printf("\t\tspeed:     %s\n", vxmod->args.bulge.speed.string);
         break;

      case SH_VXMOD_MOVE:
         printf("\n");
         printf("\t\tvector:    <%s, %s, %s>\n", vxmod->args.move.x.string, vxmod->args.move.y.string, vxmod->args.move.z.string);
         printf("\t\twaveform:  %s\n", sh_waveform_to_string(vxmod->args.move.form));
         printf("\t\tbase:      %s\n", vxmod->args.move.base.string);
         printf("\t\tamplitude: %s\n", vxmod->args.move.amp.string);
         printf("\t\tphase:     %s\n", vxmod->args.move.phase.string);
         printf("\t\tfrequency: %s\n", vxmod->args.move.freq.string);
         break;

      case SH_VXMOD_AUTOSPRITE:
      case SH_VXMOD_AUTOSPRITE2:
      case SH_VXMOD_PROJECTION_SHADOW:
      case SH_VXMOD_TEXT0:
      case SH_VXMOD_TEXT1:

      case SH_VXMOD_STENCIL_SHADOW_EXT:

         break;

      default:
         break;
   }
}



 void report_vxmods(shader_t* >shader)
{
   int i;

   if (info->shader->vxmod_count > 0) {
      printf("\ndeformVertexes:\n\n");
      printf("\tcount: %d\n", info->shader->vxmod_count);

      for (i = 0; i < info->shader->vxmod_count; i++) {
         printf("\n");
         printf("\tdeformVertexes #%d: ", i+1);
         report_vxmod(&info->shader->vxmods[i]);
      }
   }
   else {
      printf("\ndeformVertexes: <none>\n");
   }
}



 void report_fogparms(shader_t* info->shader)
{
   if (info->shader->flags & SH_FOGPARMS) {
      printf("\nfogparms:\n");
      printf("\tcolor:              <%s, %s, %s>\n", info->shader->fog_color[0].string, info->shader->fog_color[1].string, info->shader->fog_color[2].string);
      printf("\tdistance to opaque: %s\n", info->shader->fog_distance_to_opaque.string);
   }
   else {
      printf("\nfogparms: <none>\n");
   }
}



 void report_nopicmip(shader_t* info->shader)
{
   printf("\nnopicmip: ");

   if (info->shader->flags & SH_NOPICMIP) {
      printf("JE_TRUE");
   }
   else {
      printf("JE_FALSE");
   }

   printf("\n");
}



 void report_nomipmaps(shader_t* info->shader)
{
   printf("\nnomipmaps: ");

   if (info->shader->flags & SH_NOMIPMAPS) {
      printf("JE_TRUE");
   }
   else {
      printf("JE_FALSE");
   }

   printf("\n");
}



 void report_polygon_offset(shader_t* info->shader)
{
   printf("polygon offset: ");

   if (info->shader->flags & SH_POLYGON_OFFSET) {
      printf("JE_TRUE");
   }
   else {
      printf("JE_FALSE");
   }

   printf("\n");
}



 void report_sort(shader_t* info->shader)
{
   printf("\nsort priority: %s\n", sh_sort_to_string(info->shader->sort_priority, JE_FALSE));
}



 void report_entity_mergable(shader_t* info->shader)
{
   printf("\nentityMergable: ");

   if (info->shader->flags & SH_ENTITY_MERGABLE) {
      printf("JE_TRUE");
   }
   else {
      printf("JE_FALSE");
   }

   printf("\n");
}


 void report_map(sh_stage_t* stage)
{
   if (stage.anim_map_count == 1) {
      if (stage.maps[0].flags & SH_MAP_CLAMPMAP) {
         printf("\t\tclampmap: ");
      }
      else {
         printf("\t\tmap: ");
      }

      printf("%s\n", stage.maps[9].name);
   }
   else if (stage.anim_map_count > 1) {
      int i;

      printf("\t\tanimMap:\n\n");

      printf("\t\t\tfps:   %s\n", stage.anim_map_fps.string);
      printf("\t\t\tcount: %d\n\n", stage.anim_map_count);

      for (i = 0; i < stage.anim_map_count; i++) {
         printf("\t\t\tframe %d: %s\n", i+1, stage.maps[i].name);
      }
   }
   else {
      printf("\n\t\tmap: <none>\n");
   }
}



 void report_blendfunc(sh_stage_t* stage)
{
   if (stage.flags & SH_STAGE_BLENDFUNC) {
      printf("\n\t\tblendfunc: ");
      
      if (sh_is_blend_filter(stage)) {
         printf("filter\n");
      }
      else if (sh_is_blend_blend(stage)) {
         printf("blend\n");
      }
      else if (sh_is_blend_add(stage)) {
         printf("add\n");
      }
      else {
         printf("\n\n");
         printf("\t\t\tsource factor:      %s\n", sh_blend_to_string(stage.blend_src));
         printf("\t\t\tdestination factor: %s\n", sh_blend_to_string(stage.blend_dst));
      }
   }
   else {
      printf("\n\t\tblendFunc: <none>\n");
   }
}



 void report_rgbagen(sh_rgbagen_t* rgbagen, jeBoolean is_rgbgen)
{
   printf("%s\n", sh_rgbagen_to_string(rgbagen->func));

   switch(rgbagen->func) {
      case SH_RGBAGEN_WAVE:
         printf("\n");
         printf("\t\t\twaveform:  %s\n", sh_waveform_to_string(rgbagen->args.wave.form));
         printf("\t\t\tbase:      %s\n", rgbagen->args.wave.base.string);
         printf("\t\t\tamplitude: %s\n", rgbagen->args.wave.amp.string);
         printf("\t\t\tphase:     %s\n", rgbagen->args.wave.phase.string);
         printf("\t\t\tfrequency: %s\n", rgbagen->args.wave.freq.string);
         break;

      case SH_RGBAGEN_CONST_EXT:
         printf("\n\t\t\t");

         if (is_rgbgen) {
             printf("color: <%s, %s, %s>\n", rgbagen->args.constant.color[0], rgbagen->args.constant.color[1], rgbagen->args.constant.color[2]);
         }
         else {
             printf("alpha: %s\n", rgbagen->args.constant.color[0]);
         }

         break;

      case SH_RGBAGEN_ONE_MINUS_PORTAL_EXT:
      case SH_RGBAGEN_IDENTITY_LIGHTING:
      case SH_RGBAGEN_IDENTITY:
      case SH_RGBAGEN_ENTITY:
      case SH_RGBAGEN_ONE_MINUS_ENTITY:
      case SH_RGBAGEN_VERTEX:
      case SH_RGBAGEN_ONE_MINUS_VERTEX:
      case SH_RGBAGEN_PORTAL:
      case SH_RGBAGEN_LIGHTING_DIFFUSE:
      case SH_RGBAGEN_LIGHTING_SPECULAR:
      default:
         break;
   }
}

 void report_rgbgen(sh_stage_t* stage)
{
   printf("\n\t\trgbGen: ");
   report_rgbagen(&stage.rgbgen, JE_TRUE);
}



 void report_alphagen(sh_stage_t* stage)
{
   printf("\n\t\talphaGen: ");
   report_rgbagen(&stage.alphagen, JE_FALSE);
}



 void report_tcgen(sh_stage_t* stage)
{
   printf("\n\t\ttcGen: %s\n", sh_tcgen_to_string(stage.tcgen.func));

   switch(stage.tcgen.func) {
      case SH_TCGEN_VECTOR:
         printf("\n");
         printf("\t\t\ts vector:  <%s, %s, %s>\n", stage.tcgen.args.vector.sx.string, stage.tcgen.args.vector.sy.string, stage.tcgen.args.vector.sz.string);
         printf("\t\t\tt vector:  <%s, %s, %s>\n", stage.tcgen.args.vector.tx.string, stage.tcgen.args.vector.ty.string, stage.tcgen.args.vector.tz.string);
         break;

      case SH_TCGEN_SKY_EXT:
         printf("\n");
         printf("\t\t\tcloudheight:  %s\n", stage.tcgen.args.sky.cloud_height.string);
         break;

      case SH_TCGEN_BASE:
      case SH_TCGEN_LIGHTMAP:
      case SH_TCGEN_ENVIRONMENT:
      default:
         break;
   }
}



 void report_tcmod(sh_tcmod_t* tcmod)
{
   printf("%s\n", sh_tcmod_to_string(tcmod->func));

   switch (tcmod->func) {
      case SH_TCMOD_ROTATE:
         printf("\n");
         printf("\t\t\t\tspeed: %s\n", tcmod->args.rotate.speed.string);
         break;

      case SH_TCMOD_SCALE:
         printf("\n");
         printf("\t\t\t\ts: %s\n", tcmod->args.scale.s.string);
         printf("\t\t\t\tt: %s\n", tcmod->args.scale.t.string);
         break;

      case SH_TCMOD_SCROLL:
         printf("\n");
         printf("\t\t\t\ts: %s\n", tcmod->args.scroll.s.string);
         printf("\t\t\t\tt: %s\n", tcmod->args.scroll.t.string);
         break;

      case SH_TCMOD_STRETCH:
         printf("\n");
         printf("\t\t\t\twaveform:  %s\n", sh_waveform_to_string(tcmod->args.stretch.form));
         printf("\t\t\t\tbase:      %s\n", tcmod->args.stretch.base.string);
         printf("\t\t\t\tamplitude: %s\n", tcmod->args.stretch.amp.string);
         printf("\t\t\t\tphase:     %s\n", tcmod->args.stretch.phase.string);
         printf("\t\t\t\tfrequency: %s\n", tcmod->args.stretch.freq.string);
         break;

      case SH_TCMOD_TRANSFORM:
         printf("\n");
         printf("\t\t\t\tm00: %s\n", tcmod->args.transform.m00.string);
         printf("\t\t\t\tm01: %s\n", tcmod->args.transform.m01.string);
         printf("\t\t\t\tm10: %s\n", tcmod->args.transform.m10.string);
         printf("\t\t\t\tm11: %s\n", tcmod->args.transform.m11.string);
         printf("\t\t\t\tt0:  %s\n", tcmod->args.transform.t0.string);
         printf("\t\t\t\tt1:  %s\n", tcmod->args.transform.t1.string);
         break;

      case SH_TCMOD_TURB:
         printf("\n");
         printf("\t\t\t\tbase:      %s\n", tcmod->args.turb.base.string);
         printf("\t\t\t\tamplitude: %s\n", tcmod->args.turb.amp.string);
         printf("\t\t\t\tphase:     %s\n", tcmod->args.turb.phase.string);
         printf("\t\t\t\tfrequency: %s\n", tcmod->args.turb.freq.string);
         break;
   }
}



 void report_tcmods(sh_stage_t* stage)
{
   if (stage.tcmod_count > 0) {
      int i;

      printf("\n\t\ttcMods:\n\n");
      printf("\t\t\tcount: %d\n", stage.tcmod_count);

      for (i = 0; i < stage.tcmod_count; i++) {
         printf("\n");
         printf("\t\t\ttcMod #%d: ", i+1);
         report_tcmod(&stage.tcmods[i]);
      }
   }
   else {
      printf("\n\t\ttcMods: <none>\n");
   }
}



 void report_depthfunc(sh_stage_t* stage)
{
   printf("\n\t\tdepthfunc: %s\n", sh_depthfunc_to_string(stage.depthfunc));
}



 void report_depthwrite(sh_stage_t* stage)
{
   printf("\n\t\tdepthWrite: ");

   if (stage.flags & SH_STAGE_DEPTHWRITE) {
      printf("JE_TRUE");
   }
   else {
      printf("JE_FALSE");
   }

   printf("\n");
}



 void report_detail(sh_stage_t* stage)
{
   printf("\n\t\tdetail: ");

   if (stage.flags & SH_STAGE_DETAIL) {
      printf("JE_TRUE");
   }
   else {
      printf("JE_FALSE");
   }

   printf("\n");
}



 void report_alphafunc(sh_stage_t* stage)
{
   printf("\n\t\talphafunc: ");

   if (stage.flags & SH_STAGE_ALPHAFUNC) {
      printf("%s\n", sh_alphafunc_to_string(stage.alphafunc));
   }
   else {
      printf("<none>\n");
   }
}



 void report_stage(sh_stage_t* stage)
{
   report_map(stage);
   report_blendfunc(stage);
   report_rgbgen(stage);
   report_alphagen(stage);
   report_tcgen(stage);
   report_tcmods(stage);
   report_depthfunc(stage);
   report_depthwrite(stage);
   report_detail(stage);
   report_alphafunc(stage);
}



 void report_stages(shader_t* info->shader)
{
   if (info->shader->stage_count > 0) {
      int i;

      printf("\nstages:\n\n");
      printf("\tcount: %d\n", info->shader->stage_count);

      for (i = 0; i < info->shader->stage_count; i++) {
         printf("\n");
         printf("\tstage #%d: \n\n", i+1);
         report_stage(&info->shader->stages[i]);
      }
   }
   else {
      printf("\nno stages\n");
   }
}



void shader_report(shader_t* info->shader)
{
   printf("------------------------\n");
   printf("name: %s\n", info->shader->name);
   report_skyparms(info->shader);
   report_cull(info->shader);
   report_vxmods(info->shader);
   report_fogparms(info->shader);
   report_nopicmip(info->shader);
   report_nomipmaps(info->shader);
   report_polygon_offset(info->shader);
   report_sort(info->shader);
   report_entity_mergable(info->shader);
   report_stages(info->shader);
   printf("------------------------\n");
}
*/


