#include "gosGml.hpp"
#pragma warning(disable:4706)

//===========================================================================//
// File:	 Tree.cpp														 //
// Project:  gosGml				                                         //
// Contents: 																 //
//---------------------------------------------------------------------------//
// Date      Who    Modification                                             //
// 4/10/00   JR     Created													 //
//---------------------------------------------------------------------------//
// Copyright (C) 2000 Microsoft Corp.						                 //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================/

extern HGOSFONT3D gGmlFont;
extern unsigned char * gosGml_TextData;
extern GmlDisplaySystem* HDS;
extern GStack<char>* GS;
extern GStack<char>* GSF;

char* GetPathFromFFN(const char* FullFilePath);
bool DoesFilePathExist(const char* Path, const char* FileName);
char* DefaultPagePath=NULL;

int _gos_GetPage(const char* FileName, BYTE** MemoryImage, DWORD* Size)	//must use Full File Name!
{
	if(!FileName)
	{
		char* Badness=new char[16];
		mstrcpy(Badness,"<p>Bad Link</p>");
		*MemoryImage=(unsigned char*)Badness;
		*Size=16;
		return 0;
	}
	if(strlen(FileName)>7 && memcmp("http://",FileName,7))
	{
		if(!gos_DoesFileExist(FileName))
		{
			char* Badness=new char[16];
			mstrcpy(Badness,"<p>Bad Link</p>");
			*MemoryImage=(unsigned char*)Badness;
			*Size=16;
			return 0;
		}
		gos_GetFile(FileName,MemoryImage,Size);
		return 1;
	}
	else
	{
		//http file request
		return 2;
	}
}

char* _gos_LocatePage(const char* FileName)	//need to delete what you get out of this
{
	if(!FileName)	//the HELL I say!
		return NULL;
	if((strlen(FileName)>7 && memcmp("http://",FileName,7)) || (strlen(FileName)>2 && memcmp("\\\\",FileName,2))) //if not network
	{
		static char* CurrentPath=0;
		if(CurrentPath && strlen(FileName)>3 && *(FileName+1)!=':')	//if FileName is not ?:\ then use relative path
			if(!DoesFilePathExist(CurrentPath,FileName))
				if(!(DefaultPagePath && DoesFilePathExist(DefaultPagePath,FileName)))
					if(!gos_DoesFileExist(FileName))
						return NULL;
					else
						return DupStr(FileName);
				else
					return AppendStr(DefaultPagePath,FileName);
			else
				return AppendStr(CurrentPath,FileName);
		//absolute path given
		char* FPath=GetPathFromFFN(FileName);
		if(FPath)
			CurrentPath=FPath;
		if(!gos_DoesFileExist(FileName))
			return NULL;
		return DupStr(FileName);
	}
	else //network style
	{
		return NULL;
	}
}

void _gos_SetDefaultPath(const char* Path)
{
	if(DefaultPagePath)
		delete[] DefaultPagePath;
	DefaultPagePath=DupStr(Path);
}

bool DoesFilePathExist(const char* Path, const char* FileName)
{
	char* FFN=AppendStr(Path,FileName);
	bool retval = gos_DoesFileExist(FFN);
	delete[] FFN;
	return retval;
}

char* GetPathFromFFN(const char* FullFilePath)	//full file name desu ne
{
	if(!FullFilePath)
		return 0;
	char* LastSlash=(char*)FullFilePath+strlen(FullFilePath)-1;
	while(*LastSlash!='\\' && *LastSlash!='/' && LastSlash>=FullFilePath)
		LastSlash--;
	if(LastSlash==FullFilePath)
		return 0;
	char* PathOnly=new char[LastSlash-FullFilePath+2];//you'll probably see 1 of these leaked, which is why you're here. 1 will probably leak, but no more than that. I may fix this later, but a few bytes isn't a big deal... just looks bad.
	memcpy(PathOnly, FullFilePath, LastSlash-FullFilePath+1);
	*(PathOnly+(int)(LastSlash-FullFilePath+1))=0;
	return PathOnly;
}

int _stdcall SetTab(void * instance, int nargs, void * args[16]){
	STOP(("SetTab not implemented"));
	instance; nargs; args;
	return 0;
}

int _stdcall TextSideDraw(void * instance, int nargs, void * args[16]){
	instance; nargs;
	rect DisplayArea;
	DisplayArea.Bottom=*((int*)args[3]);
	DisplayArea.Left=*((int*)args[0]);
	DisplayArea.Right=*((int*)args[2]);
	DisplayArea.Top=*((int*)args[1]);
	int left = DisplayArea.Left=*((int*)args[0]);
	int top = DisplayArea.Top=*((int*)args[1]);
	int right = DisplayArea.Right=*((int*)args[2]);
	int bottom = DisplayArea.Bottom=*((int*)args[3]);
	int line_no = *((int*)args[4]);
	//char cGmlLine;
	//int len;
	gos_TextSetRegion(left,top,right,bottom);
	gos_TextSetAttributes(gGmlFont, 0xffffffff,1,1,1,0,0,0);
	gos_TextSetPosition(left,top-(line_no*12));
	if( !HDS )
	{
		HDS = new GmlDisplaySystem("assets\\fonts\\", "assets\\Graphics\\", &DisplayArea);
	}
	if (gosGml_TextData&&HDS) 
	{
		return HDS->TextDrawGml((char*)gosGml_TextData);
	}

	return 0;
}

void _stdcall LoadDefaultPage(const char* lp){
	unsigned long size = 0;
	char* lpr = _gos_LocatePage(lp);
	_gos_GetPage(lpr, &gosGml_TextData, &size);
	if(lpr)
		delete[] lpr;
	gosGml_TextData[size-1] = 0;  //don't even ask
}

int _stdcall BackGotClickCB(void * instance, int nargs, void * args[16])
{
	instance;nargs;args;
	return BackGotClick();
}

int BackGotClick()
{
	
	char* Target=HistoryBack();
	if(Target)
	{
		if (gosGml_TextData)
		{
			gos_Free(gosGml_TextData);
			gosGml_TextData = 0;
		}
		unsigned long size = 0;
		char* Tr = _gos_LocatePage(Target);
		_gos_GetPage(Tr, &gosGml_TextData, &size);
		if(Tr)
			delete[] Tr;
		gosGml_TextData[size-1] = 0;  //don't even ask
	}
	return 0;
}

int _stdcall ForwardsGotClickCB(void * instance, int nargs, void * args[16])
{
	instance;nargs;args;
	return ForwardsGotClick();
}

int ForwardsGotClick(){

	char* Target=HistoryForwards();
	if(Target)
	{
		if (gosGml_TextData)
		{
			gos_Free(gosGml_TextData);
			gosGml_TextData = 0;
		}
		unsigned long size = 0;
		char* Tr = _gos_LocatePage(Target);
		_gos_GetPage(Tr, &gosGml_TextData, &size);
		if(Tr)
			delete[] Tr;
		gosGml_TextData[size-1] = 0;  //don't even ask
	}
	return 0;
}

void _stdcall HistoryAddCB(void * instance, int nargs, void * args[16])
{
	instance;nargs;args;
	HistoryAdd((char*)args[0]);
}

//call whenever a link is clicked. should always be adding the destination page.
void HistoryAdd(char* Str)
{
	if(!GS)	GS=new GStack<char>();
	if(GSF)
	{
		delete GSF;
		GSF=NULL;
	}
	GS->Push(Str);
}

//pack button pressed
char* HistoryBack()
{
	char* PopString=NULL;
	if(!GSF) GSF=new GStack<char>();
	if(GS)
	{
		PopString=GS->Pop(); //returns page you are currently on
		if(PopString)
			GSF->Push(PopString);//push current page to forwards list
		PopString=GS->Pop(); //returns the back page
		if(PopString)
			GS->Push(PopString); //push back page to back list
	}
	return PopString;
}

bool BackIsEmpty()
{
	if(!GS)	GS=new GStack<char>();
	return GS->IsEmpty();
}

//forwards button pressed
char* HistoryForwards()
{
	char* PopString=NULL;
	if(GSF&&GS)
	{
		PopString=GSF->Pop();
		if(PopString)
			GS->Push(PopString);
	}
	return PopString;
}

bool ForwardsIsEmpty()
{
	if(!GSF) GSF=new GStack<char>();
	return GSF->IsEmpty();
}

void HistoryClear()
{
	char* victim;
	if(GS)
		while((victim=GS->Pop()))
			delete[] victim;
	if(GSF)
		while((victim=GSF->Pop()))
			delete[] victim;
}

char* _stdcall RawTextGotClick(int x, int y)
{
	return HDS->TestForHit(x,y);
}

int _stdcall TextGotClick(void * instance, int nargs, void * args[16])
{//got a click. hit test, and if the click was on a link then change the page.
	instance; nargs;
	int iRelX =  *((int*)args[1]);
	int iRelY =  *((int*)args[0]);
	char* link=HDS->TestForHit(iRelX,iRelY);
	if(link)
	{
		gos_Free(gosGml_TextData);
		gosGml_TextData = 0;
		unsigned long size = 0;
		char* lr = _gos_LocatePage(link);
		_gos_GetPage(lr, &gosGml_TextData, &size);
		if(lr)
			delete[] lr;
		char Temp=gosGml_TextData[size-1];
		gosGml_TextData[size-1] = 0;  //don't even ask
		char* TempP=new char[mstrlen((char*)gosGml_TextData)+2];
		mstrcpy(TempP,(char*)gosGml_TextData);
		TempP[size]=0;
		TempP[size-1]=Temp;
		HistoryAdd(TempP);
		return 1;
	}
	return 0;
}

SearchRes* Search(const char* Target) //stub stub stub
{
	STOP(("Search not implemented"));
	Target;
	return NULL;
}

void Jump(const char* Target)
{
		gos_Free(gosGml_TextData);
		gosGml_TextData = 0;
		unsigned long size = 0;
		char* Tr = _gos_LocatePage(Target);
		_gos_GetPage(Tr, &gosGml_TextData, &size);
		if(Tr)
			delete[] Tr;
		char Temp=gosGml_TextData[size-1];
		gosGml_TextData[size-1] = 0;  //don't even ask
		char* TempP=new char[mstrlen((char*)gosGml_TextData)+2];
		mstrcpy(TempP,(char*)gosGml_TextData);
		TempP[size]=0;
		TempP[size-1]=Temp;
		HistoryAdd(TempP);
}

#pragma warning(default:4706)