#include "Script.hpp"


extern OBJECT * pFocusedObject;
extern char * ErrorTitle;
extern int ScriptSP;
extern SCRIPTSTACK ScriptStack[];

				   
#ifdef LAB_ONLY
//
// Print Out the member information of the last known pObject...
//
char * _stdcall ErrorOnCrash()
{
	static char ScriptErrorBuffer[16384];
	ScriptErrorBuffer[0] = 0;
	char tmpBuff[8192];
	OBJECT * obj = pObject;

	// return if the last object isn't known
	if (!obj)
		return NULL;
	// return if the last object is corrupt
	if (obj == (OBJECT *) 0xff81ff81)
		return NULL;

	// show callstack:
	strcpy(ScriptErrorBuffer, "Execution Stack:\n==================\n");
	sprintf(tmpBuff, "%s(%d)\n",  pLongFileName, CurrentLineNumber);
	strcat(ScriptErrorBuffer, tmpBuff);
	for(int i=ScriptSP; i >0; i--)
	{
		sprintf(tmpBuff, "%s(%d)\n",  ScriptStack[i].pFileName, ScriptStack[i].CurrentLineNumber);
		strcat(ScriptErrorBuffer, tmpBuff);
	}

	strcat(ScriptErrorBuffer, "\nLast Processed Object:\n========================\n");

	if (obj->pParentVariable && obj->pParentVariable->ArraySize)
	{
		int num; 
		for(num = 0; num < obj->pParentVariable->ArraySize; num++) 
		{
			if (obj == (OBJECT *) obj->pParentVariable->pCubes[num])
				break;
		}
		sprintf( tmpBuff,  "OBJECT %s[%d] running %s (%s), child of %s\n", obj->Name, num, obj->pFunction->Name, obj == pFocusedObject ? "HAS FOCUS" : "NOT FOCUSED", obj->pParentObject ? obj->pParentObject->Name : "None");
		strcat(ScriptErrorBuffer, tmpBuff);
	}
	else
	{
		sprintf( tmpBuff,  "OBJECT %s running %s (%s), child of %s\n", obj->Name, obj->pFunction->Name, obj == pFocusedObject ? "HAS FOCUS" : "NOT FOCUSED",obj->pParentObject ? obj->pParentObject->Name : "None");
		strcat(ScriptErrorBuffer, tmpBuff);
	}

	VARIABLE * tmp = obj->pVariables;
	while(tmp)
	{
		switch(tmp->Type)
		{
		case VAR_INT:
			{
				if (tmp->ArraySize)
				{
					for(int i=0; i < tmp->ArraySize; i++)
					{
						sprintf( tmpBuff,  "INT %s[%d] = %d (0x%x)\n", tmp->Name, i, tmp->pValues[i], tmp->Value );
						strcat(ScriptErrorBuffer, tmpBuff);
					}
				}
				else
				{
					sprintf( tmpBuff,  "INT %s = %d (0x%x)\n", tmp->Name, tmp->Value, tmp->Value );
					strcat(ScriptErrorBuffer, tmpBuff);
				}
			}
			break;
		case VAR_FLOAT:
			{
				if (tmp->ArraySize)
				{
					for(int i=0; i < tmp->ArraySize; i++)
					{
						sprintf( tmpBuff,  "FLOAT %s[%d] = %.2f\n", tmp->Name, i, tmp->pfValues[i] );
						strcat(ScriptErrorBuffer, tmpBuff);
					}
				}
				else
				{
					sprintf( tmpBuff,  "FLOAT %s = %.2f\n", tmp->Name, tmp->fValue );
				 	strcat(ScriptErrorBuffer, tmpBuff);
				}
			}
			break;
		case VAR_STRING: 
			{
				if (tmp->ArraySize)
				{
					for(int i=0; i < tmp->ArraySize; i++)
					{
						if (tmp->pValues[i])
							sprintf( tmpBuff,  "STRING %s[%d] = \"%s\"\n", tmp->Name, i, tmp->pValues[i] );
						else
							sprintf( tmpBuff,  "STRING %s[%d] = undefined\n", tmp->Name, i ); 
						strcat(ScriptErrorBuffer, tmpBuff);
					}
				}
				else
				{
					if (tmp->pString)
						sprintf( tmpBuff,  "STRING %s = \"%s\"\n", tmp->Name, tmp->pString );
					else
						sprintf( tmpBuff,  "STRING %s = undefined\n", tmp->Name ); 
					strcat(ScriptErrorBuffer, tmpBuff);
				}
			}
			break;
		case VAR_POSITION: 
			{
				if (tmp->ArraySize)
				{
					for(int i=0; i < tmp->ArraySize; i++)
					{
						if (tmp->pPositions[i])
							sprintf( tmpBuff,  "POSITION %s[%d] = ( %d, %d, %d )\n", tmp->Name, i, tmp->pPositions[i]->x, tmp->pPositions[i]->y, tmp->pPositions[i]->z );
						else
							sprintf( tmpBuff,  "POSITION %s[%d] = undefined\n", tmp->Name, i ); 
						strcat(ScriptErrorBuffer, tmpBuff);
					}
				}
				else
				{
					if (tmp->pPosition)
						sprintf( tmpBuff,  "POSITION %s = ( %d, %d, %d )\n", tmp->Name, tmp->pPosition->x, tmp->pPosition->y, tmp->pPosition->z );
					else
						sprintf( tmpBuff,  "POSITION %s = undefined\n", tmp->Name ); 
					strcat(ScriptErrorBuffer, tmpBuff);
				}
			}
			break;
		case VAR_BITMAP:
			{
				if (tmp->ArraySize)
				{
					for(int i=0; i < tmp->ArraySize; i++)
					{
						if (tmp->pSurfaces[i])
						{
							char * name = NULL;
							name = tmp->pSurfaces[i]->m_lpPath;
							sprintf( tmpBuff,  "BITMAP %s[%d] = \"%s\", size(%d x %d)\n", 
								tmp->Name, i, name, tmp->pSurfaces[i]->m_nativeFormat.m_width, tmp->pSurfaces[i]->m_nativeFormat.m_height );
						}
						else
							sprintf( tmpBuff,  "BITMAP %s[%d] = undefined\n", tmp->Name, i ); 
						strcat(ScriptErrorBuffer, tmpBuff);
					}
				}
				else
				{
					if (tmp->Surface)
					{
						char * name = NULL;
						name = tmp->Surface->m_lpPath;
						sprintf( tmpBuff,  "BITMAP %s = \"%s\", size(%d x %d)\n", 
							tmp->Name, name, tmp->Surface->m_nativeFormat.m_width, tmp->Surface->m_nativeFormat.m_height );
					}
					else
					{
						sprintf( tmpBuff,  "BITMAP %s = undefined\n", tmp->Name ); 
						strcat(ScriptErrorBuffer, tmpBuff);
					}
				}
			}
			break;
		case VAR_OBJECT: 
			{
				if (tmp->ArraySize)
				{
					for(int i=0; i < tmp->ArraySize; i++)
					{
						if (tmp->pValues[i])
						{
							OBJECT * o = (OBJECT *) tmp->pValues[i];
							sprintf( tmpBuff,  "OBJECT %s[%d] = running %s, framerate %d, region (%d, %d to %d, %d), position (%d, %d, %d)\n", 
								o->Name, i, o->pFunction ? o->pFunction->Name: "(none)", *o->FrameRate,
								o->Cube->p1.x, o->Cube->p1.y, o->Cube->p2.x, o->Cube->p2.y, 
								o->Coordinates->x, o->Coordinates->y, o->Coordinates->z );
						}
						else
							sprintf( tmpBuff,  "OBJECT %s[%d] = undefined\n", tmp->Name, i ); 
						strcat(ScriptErrorBuffer, tmpBuff);
					}
				}
				else
				{
					if (tmp->Value)
					{
						OBJECT * o = (OBJECT *) tmp->Value;
						sprintf( tmpBuff,  "OBJECT %s = running %s, framerate %d, region (%d, %d to %d, %d), position (%d, %d, %d)\n", 
							o->Name, o->pFunction ? o->pFunction->Name: "(none)", *o->FrameRate, 	
							o->Cube->p1.x, o->Cube->p1.y, o->Cube->p2.x, o->Cube->p2.y, 
							o->Coordinates->x, o->Coordinates->y, o->Coordinates->z );
						strcat(ScriptErrorBuffer, tmpBuff);
					}
					else
					{
						sprintf( tmpBuff,  "OBJECT %s = undefined\n", tmp->Name ); 
						strcat(ScriptErrorBuffer, tmpBuff);
					}
				}
			}
			break;
		case VAR_FONT:
			{
				if (tmp->ArraySize)
				{
					for(int i=0; i < tmp->ArraySize; i++)
					{
						if (tmp->pValues[i])
						{
							char * name = NULL;
							name = ((Surface *) tmp->pValues[i])->m_lpPath;
							sprintf( tmpBuff,  "FONT %s[%d] = \"%s\"\n", tmp->Name, i, name );
						}
						else
							sprintf( tmpBuff,  "FONT %s[%d] = undefined\n", tmp->Name, i ); 
						strcat(ScriptErrorBuffer, tmpBuff);
					}
				}
				else
				{
					if (tmp->Value)
					{
						char * name = NULL;
						name = ((Surface *) tmp->Value)->m_lpPath;
						sprintf( tmpBuff,  "FONT %s = \"%s\"\n", tmp->Name, name );
					}
					else
						sprintf( tmpBuff,  "FONT %s = undefined\n", tmp->Name ); 
					strcat(ScriptErrorBuffer, tmpBuff);
				}
			}
			break;
		case VAR_SOUND: 
 			{
				if (tmp->ArraySize)
				{
					for(int i=0; i < tmp->ArraySize; i++)
					{
						if (tmp->pSounds[i])
						{
							gosAudio_ResourceInfo ga_ri;
							gosAudio_GetResourceInfo(tmp->pSounds[i], &ga_ri);
							sprintf( tmpBuff,  "SOUND %s[%d] = \"%s\"\n", tmp->Name, i, ga_ri.lpstrPath );
						}
						else
							sprintf( tmpBuff,  "SOUND %s[%d] = undefined\n", tmp->Name, i );
						strcat(ScriptErrorBuffer, tmpBuff);
					}
				}
				else
				{
					if (tmp->Sound)
					{
						gosAudio_ResourceInfo ga_ri;
						gosAudio_GetResourceInfo(tmp->Sound, &ga_ri);
						sprintf( tmpBuff,  "SOUND %s = \"%s\"\n", tmp->Name,  ga_ri.lpstrPath );
					}
					else
						sprintf( tmpBuff,  "SOUND %s = undefined\n", tmp->Name );
					strcat(ScriptErrorBuffer, tmpBuff);
				}
			}
			break;
		case VAR_CUBE:
			{
				if (tmp->ArraySize)
				{
					for(int i=0; i < tmp->ArraySize; i++)
					{
						if (tmp->pCubes[i])
						{
							sprintf( tmpBuff,  "CUBE %s[%d] = ( %d, %d to %d, %d )\n", tmp->Name, i, tmp->pCubes[i]->p1.x, tmp->pCubes[i]->p1.y, tmp->pCubes[i]->p2.x, tmp->pCubes[i]->p2.y );
						}
						else
							sprintf( tmpBuff,  "CUBE %s[%d] = undefined\n", tmp->Name, i );
						strcat(ScriptErrorBuffer, tmpBuff);
					}
				}
				else
				{
					if (tmp->pCube)
					{
						sprintf( tmpBuff,  "CUBE %s = ( %d, %d to %d, %d )\n", tmp->Name, tmp->pCube->p1.x, tmp->pCube->p1.y, tmp->pCube->p2.x, tmp->pCube->p2.y );
					}
					else
						sprintf( tmpBuff,  "CUBE %s = undefined\n", tmp->Name );
					strcat(ScriptErrorBuffer, tmpBuff);
				}
			}
			break;
		case VAR_MOVIE: 
			{
				if (tmp->ArraySize)
				{
					for(int i=0; i < tmp->ArraySize; i++)
					{
						if (tmp->pVideos[i])
						{
							gosVideo_ResourceInfo gv_ri;
							gosVideo_GetResourceInfo(tmp->pVideos[i], &gv_ri);
							sprintf( tmpBuff,  "MOVIE %s[%d] = \"%s\"\n", 
								tmp->Name, i, gv_ri.lpstrPath  );
						}
						else
							sprintf( tmpBuff,  "MOVIE %s[%d] = undefined\n", tmp->Name, i ); 
						strcat(ScriptErrorBuffer, tmpBuff);
					}
				}
				else
				{
					if (tmp->Video)
					{
						gosVideo_ResourceInfo gv_ri;
						gosVideo_GetResourceInfo(tmp->Video, &gv_ri);
						sprintf( tmpBuff,  "MOVIE %s = \"%s\"\n", 
							tmp->Name, tmp->Name, gv_ri.lpstrPath   );
					}
					else
						sprintf( tmpBuff,  "MOVIE %s = undefined\n", tmp->Name ); 
					strcat(ScriptErrorBuffer, tmpBuff);
				}
			}
			break;
		case VAR_GAF:
			{
				if (tmp->ArraySize)
				{
					for(int i=0; i < tmp->ArraySize; i++)
					{
						if (tmp->pGAFs[i])
						{
							sprintf( tmpBuff,  "GAF %s[%d] = \"%s\", size(%d, %d), frame %d of %d\n", 
								tmp->Name, i, tmp->pGAFs[i]->m_primarySurface->m_lpPath, 
								tmp->pGAFs[i]->m_gafHeader->m_width, tmp->pGAFs[i]->m_gafHeader->m_height, tmp->pGAFs[i]->m_lastFrame, tmp->pGAFs[i]->m_gafHeader->m_totalImages );
						}
						else
							sprintf( tmpBuff,  "GAF %s[%d] = undefined\n", tmp->Name, i ); 
						strcat(ScriptErrorBuffer, tmpBuff);
					}
				}
				else
				{
					if (tmp->Gaf)
					{
						sprintf( tmpBuff,  "GAF %s = \"%s\", size(%d, %d), frame %d of %d\n", 
								tmp->Name, tmp->Gaf->m_primarySurface->m_lpPath, 
								tmp->Gaf->m_gafHeader->m_width, tmp->Gaf->m_gafHeader->m_height, tmp->Gaf->m_lastFrame, tmp->Gaf->m_gafHeader->m_totalImages );
					}
					else
						sprintf( tmpBuff,  "GAF %s = undefined\n", tmp->Name ); 
					strcat(ScriptErrorBuffer, tmpBuff);
				}
			}
			break;
		case VAR_PANE: 
			{
				if (tmp->ArraySize)
				{
					for(int i=0; i < tmp->ArraySize; i++)
					{
						if (tmp->pPanes[i])
						{
							char * name = NULL;
							name = tmp->pPanes[i]->GetSurfacePath();
							sprintf( tmpBuff,  "PANE %s[%d] = \"%s\", size(%d x %d), origin(%d, %d), rot( %d, %d, %d), scale(%d, %d)\n", 
								tmp->Name, i, name,
								tmp->pPanes[i]->m_pTextureList->m_width, tmp->pPanes[i]->m_pTextureList->m_height, 
								(int) tmp->pPanes[i]->currentOffset.x, (int) tmp->pPanes[i]->currentOffset.y, 
								(tmp->pPanes[i]->currentRotation.x*360.0f) / 6.28f, (tmp->pPanes[i]->currentRotation.y*360.0f) / 6.28f, (tmp->pPanes[i]->currentRotation.z*360.0f) / 6.28f,
								(int)tmp->pPanes[i]->currentScaleX, (int)tmp->pPanes[i]->currentScaleY);
						}
						else
							sprintf( tmpBuff,  "PANE %s[%d] = undefined\n", tmp->Name, i ); 
						strcat(ScriptErrorBuffer, tmpBuff);
					}
				}
				else
				{
					if (tmp->Pane)
					{
						char * name = NULL;
						name = tmp->Pane->GetSurfacePath();
						sprintf( tmpBuff,  "PANE %s = \"%s\", size(%d x %d), origin(%d, %d), rot( %d, %d, %d), scale(%d, %d)\n", 
							tmp->Name, name,
							tmp->Pane->m_pTextureList->m_width, tmp->Pane->m_pTextureList->m_height, 
							(int) tmp->Pane->currentOffset.x, (int) tmp->Pane->currentOffset.y, 
							(tmp->Pane->currentRotation.x*360.0f) / 6.28f, (tmp->Pane->currentRotation.y*360.0f) / 6.28f, (tmp->Pane->currentRotation.z*360.0f) / 6.28f,
							(int)tmp->Pane->currentScaleX, (int)tmp->Pane->currentScaleY);
					}
					else
						sprintf( tmpBuff,  "PANE %s = undefined\n", tmp->Name ); 
					strcat(ScriptErrorBuffer, tmpBuff);
				}
			}
			break;
		case VAR_FONT3D:
			{
				if (tmp->ArraySize)
				{
					for(int i=0; i < tmp->ArraySize; i++)
					{
						if (tmp->pSurfaces[i])
							sprintf( tmpBuff,  "FONT3D %s[%d] = (unknown)\n", tmp->Name, i );
						else
							sprintf( tmpBuff,  "FONT3D %s[%d] = undefined\n", tmp->Name, i ); 
						strcat(ScriptErrorBuffer, tmpBuff);
					}
				}
				else
				{
					if (tmp->Surface)
						sprintf( tmpBuff,  "FONT3D %s = (unknown)\n", tmp->Name );
					else
						sprintf( tmpBuff,  "FONT3D %s = undefined\n", tmp->Name ); 
					strcat(ScriptErrorBuffer, tmpBuff);
				}
			}
			break;
		case VAR_LIST:
			{
				if (tmp->ArraySize)
				{
					for(int i=0; i < tmp->ArraySize; i++)
					{
						sprintf( tmpBuff,  "LIST %s[%d] with %d items\n", tmp->Name, i, tmp->pLists[i]->Length());
						strcat(ScriptErrorBuffer, tmpBuff);
					}
				}
				else
				{
					sprintf( tmpBuff,  "LIST %s with %d items\n", tmp->Name, tmp->pList->Length() ); 
					strcat(ScriptErrorBuffer, tmpBuff);
				}
			}
			break;
		}
		tmp = tmp->pNext;
	}
	return ScriptErrorBuffer;
}

#endif












//
// An error occured during script processing
//
void ScriptError( char* Error, ...)
{
	char FileInfo[1024];
	char ErrorBuffer[1024];
	static char FileNameBuffer[256];

	FileInfo[0]=0;
	if( pScript && (int)pScript!=0xff81ff81 && pFileName )
	{
		gos_GetFullPathName( FileNameBuffer, pLongFileName );
		gosErrorFile=FileNameBuffer;
		char* pShortFile=FileNameBuffer+strlen(FileNameBuffer);
		while( FileNameBuffer!=pShortFile && *(pShortFile-1)!='\\' )
			pShortFile--;
		gosErrorLine=CurrentLineNumber;
		ErrorTitle="GOSSCRIPT";
		sprintf(FileInfo, "%s(%d) : ",pShortFile,CurrentLineNumber);
	}
	else
	{
		gosErrorFile=0;
		ErrorTitle="GOSSCRIPT";
		sprintf(FileInfo, "Unknown File : ");
	}
									 
	vsprintf( ErrorBuffer, Error, (char*)(&Error+1) );

	strcat( FileInfo,ErrorBuffer );

#ifdef LAB_ONLY
//
// Show extra gosScript information on LAB only builds
//
	char* (__stdcall *GameInfoSave)() = Environment.GetGameInformation;
	Environment.GetGameInformation = ErrorOnCrash;
	if( ErrorHandler( gos_ErrorFileLine | gos_ErrorNoContinue | gos_ErrorDump | gos_ErrorGameInfoFirst, FileInfo ) )
		_asm int 3
	Environment.GetGameInformation = GameInfoSave;
#else
//
// Otherwise, just show error
//
	if( ErrorHandler( gos_ErrorMessage | gos_ErrorNoContinue, FileInfo ) )
		_asm int 3
#endif

}



#if (DISTRIBUTED_GOSSCRIPT == 0)
//
// Function to return a line from a given filename/line
//
extern char* GetLineFromFile( char* tempLine, char* FileName, int LineNumber );
extern char* (__stdcall *SavedGetGameInformation)();
extern bool InScriptRender;
extern "C" void __stdcall OutputDebugStringA( const char * String );

//
// Called when a GameOS routine crashes during script execution or rendering
//
char* __stdcall ErrorInScript()
{
	static char FileInfo[4096];
	char LineBuffer[1024];
	char* Where;
	char* GameInfo=SavedGetGameInformation ? SavedGetGameInformation() : 0;
	if( 0==GameInfo || *GameInfo==0 )
		GameInfo="";

	if( InScriptRender )
		Where="\n\ngosScript\n=========\nError during Script Render\n";
	else
		Where="\n\ngosScript\n=========\nError during Script Execute\n";
	
	if( pScript && (int)pScript != 0xff81ff81 && pFileName )
	{
		char* ScriptLine=GetLineFromFile( LineBuffer, pFileName, CurrentLineNumber);
		char OutputBuffer[1024];
		char FullPath[256];
		gos_GetFullPathName( FullPath, pFileName );
		sprintf( OutputBuffer, "%s(%d) : %s\n", FullPath, CurrentLineNumber, LineBuffer );
		OutputDebugStringA( OutputBuffer );

		sprintf(FileInfo, "%s%s\nFile        : %s\nLine number : %d\nScript code : %s",GameInfo,Where,pFileName,CurrentLineNumber,ScriptLine );
	}
	else
	{
		sprintf(FileInfo, "%s%s\nUnknown Script File",GameInfo,Where );
	}
	return FileInfo;
}

#endif //DISTRIBUTED_GOSSCRIPT