/**********************************************************************
 *<
	FILE: Poltest.cpp

	DESCRIPTION:	Appwizard generated plugin

	CREATED BY: 

	HISTORY: 

 *>	Copyright (c) 1997, All Rights Reserved.
 **********************************************************************/

#include "Poltest.h"
#include <fstream.h>
#include <iostream.h>





#define POLTEST_CLASS_ID	Class_ID(0x1f668f07, 0x59603135)

ClassDesc* GetPoltestDesc();

HINSTANCE hInstance;
int controlsInit = FALSE;

// This function is called by Windows when the DLL is loaded.  This 
// function may also be called many times during time critical operations
// like rendering.  Therefore developers need to be careful what they
// do inside this function.  In the code below, note how after the DLL is
// loaded the first time only a few statements are executed.

BOOL WINAPI DllMain(HINSTANCE hinstDLL,ULONG fdwReason,LPVOID lpvReserved)
{
	hInstance = hinstDLL;				// Hang on to this DLL's instance handle.

	if (!controlsInit) {
		controlsInit = TRUE;
		InitCustomControls(hInstance);	// Initialize MAX's custom controls
		InitCommonControls();			// Initialize Win95 controls
	}
			
	return (TRUE);
}

// This function returns a string that describes the DLL and where the user
// could purchase the DLL if they don't have it.
__declspec( dllexport ) const TCHAR* LibDescription()
{
	return GetString(IDS_LIBDESCRIPTION);
}

// This function returns the number of plug-in classes this DLL
//TODO: Must change this number when adding a new class
__declspec( dllexport ) int LibNumberClasses()
{
	return 1;
}

// This function returns the number of plug-in classes this DLL
__declspec( dllexport ) ClassDesc* LibClassDesc(int i)
{
	switch(i) {
		case 0: return GetPoltestDesc();
		default: return 0;
	}
}

// This function returns a pre-defined constant indicating the version of 
// the system under which it was compiled.  It is used to allow the system
// to catch obsolete DLLs.
__declspec( dllexport ) ULONG LibVersion()
{
	return VERSION_3DSMAX;
}

TCHAR *GetString(int id)
{
	static TCHAR buf[256];

	if (hInstance)
		return LoadString(hInstance, id, buf, sizeof(buf)) ? buf : NULL;
	return NULL;
}

//
// =====================  Textparts =====================================
//

class Textparts
{
	public:
		TCHAR nodeName[256];
		TCHAR matName[256];
		
		int type, uflip, vflip, wflip, cap, channel, axis;	
		float utile, vtile, wtile, length, width, height;

		Matrix3 tm;

		Textparts(INode *node);		// contstructor to fill in a Textparts.
		Textparts();				// constructor of making a blank Textparts.
		~Textparts();

		void writeNode(ostream &stream);			// writes node information to stream
		int readNode(TCHAR *data, long position);				// reads stream and puts it into Textparts object
		void setNode(INode *node);					// writes node information to Textparts object
		void putNode(INode *node, Interface *ip);	// writes Textparts information to node
};

Textparts::Textparts()  
{
	memset(nodeName, '\0',256);
	memset(matName, '\0',256);
	tm.IdentityMatrix();
	type = 0;
	uflip = 0;
	vflip = 0;
	wflip = 0;
	cap = 0;
	channel = 0;
	utile = 0.0f;
	vtile = 0.0f;
	wtile = 0.0f;
	length = 0.0f;
	width = 0.0f;
	height = 0.0f;
	axis = 2;
}

Textparts::Textparts(INode *node)
{
	int children = 0;
	int numMods = 0;
	Object *object;
	IDerivedObject *derivedObject;
	Mtl *mat;
	SClass_ID objectSID;
	MapMod *mapMod;
	TimeValue t = 0;
	TCHAR *nameOfNode;
	TSTR nameOfMat;


	nameOfNode = node->GetName();	
	_tcscpy(nodeName, nameOfNode);
	children = node->NumberOfChildren();
	mat = node->GetMtl();			
	object = node->GetObjectRef();
	objectSID = object->SuperClassID();
	nameOfMat = mat->GetName();
	_tcscpy(matName, nameOfMat);

	if(objectSID == GEN_DERIVOB_CLASS_ID)
	{
		derivedObject = (IDerivedObject*) object;
		numMods = derivedObject->NumModifiers();
		Modifier *genericModifier;
		for(int i=0;i<numMods;i++)		// cycle through modifiers 
		{								// to get mapping modifier
			genericModifier = derivedObject->GetModifier(i);
			SClass_ID sID = genericModifier->SuperClassID();
			Class_ID cID = genericModifier->ClassID();
			if(cID.PartA()== 0xf72b1 && cID.PartB()==0x00) // found map mod.
			{
				mapMod = (MapMod*)genericModifier;
				mapMod->pblock->GetValue(PB_MAPTYPE,t,type,FOREVER);
				mapMod->pblock->GetValue(PB_UTILE,t,utile,FOREVER);
				mapMod->pblock->GetValue(PB_VTILE,t,vtile,FOREVER);
				mapMod->pblock->GetValue(PB_WTILE,t,wtile,FOREVER);
				mapMod->pblock->GetValue(PB_UFLIP,t,uflip,FOREVER);
				mapMod->pblock->GetValue(PB_VFLIP,t,vflip,FOREVER);
				mapMod->pblock->GetValue(PB_WFLIP,t,wflip,FOREVER);
				mapMod->pblock->GetValue(PB_LENGTH,t,length,FOREVER);
				mapMod->pblock->GetValue(PB_WIDTH,t,width,FOREVER);
				mapMod->pblock->GetValue(PB_HEIGHT,t,height,FOREVER);
				mapMod->pblock->GetValue(PB_CAP,t,cap,FOREVER);
				mapMod->pblock->GetValue(PB_CHANNEL,t,channel,FOREVER);	

#if 0
				//JOSE'S CODE
				Matrix3 nodeTM, orgTM;
				orgTM = node->GetNodeTM(0);
				mapMod->tmControl->GetValue(t,&nodeTM,FOREVER,CTRL_RELATIVE);
				tm = orgTM * nodeTM;
				AffineParts outparts;
				decomp_affine(tm, &outparts);
#else
				// JERRY'S CODE
				Matrix3 nodeTM(1), orgTM(1);
				orgTM = node->GetNodeTM(0);
				mapMod->tmControl->GetValue(t,&nodeTM,FOREVER,CTRL_RELATIVE);
				tm = Inverse(orgTM) * nodeTM;
#endif
			}
		}
	}
}

Textparts::~Textparts()
{
}

void Textparts::setNode(INode *node)
{
	int children = 0;
	int numMods = 0;
	Object *object;
	IDerivedObject *derivedObject;
	Mtl *mat;
	SClass_ID objectSID;
	MapMod *mapMod;
	TimeValue t = 0;
	int multipleDerived = 0;
	TCHAR *nameOfNode;
	TSTR nameOfMat;

	nameOfNode = node->GetName();
	_tcscpy(nodeName, nameOfNode);
	children = node->NumberOfChildren();
	mat = node->GetMtl();
	object = node->GetObjectRef();
	objectSID = object->SuperClassID();
	nameOfMat = mat->GetName();
	_tcscpy(matName, nameOfMat);

	while((multipleDerived != 1)&&(objectSID == GEN_DERIVOB_CLASS_ID))  // need multiple derived object support
	{
		derivedObject = (IDerivedObject*) object;
		numMods = derivedObject->NumModifiers();
		Modifier *genericModifier;
		for(int i=0;i<numMods;i++)		// cycle through modifiers 
		{								// to get mapping modifier
			genericModifier = derivedObject->GetModifier(i);
			SClass_ID sID = genericModifier->SuperClassID();
			Class_ID cID = genericModifier->ClassID();
			if(cID.PartA()== 0xf72b1 && cID.PartB()==0x00) // found map mod.
			{
				mapMod = (MapMod*)genericModifier;
				mapMod->pblock->GetValue(PB_MAPTYPE,t,type,FOREVER);
				mapMod->pblock->GetValue(PB_UTILE,t,utile,FOREVER);
				mapMod->pblock->GetValue(PB_VTILE,t,vtile,FOREVER);
				mapMod->pblock->GetValue(PB_WTILE,t,wtile,FOREVER);
				mapMod->pblock->GetValue(PB_UFLIP,t,uflip,FOREVER);
				mapMod->pblock->GetValue(PB_VFLIP,t,vflip,FOREVER);
				mapMod->pblock->GetValue(PB_WFLIP,t,wflip,FOREVER);
				mapMod->pblock->GetValue(PB_LENGTH,t,length,FOREVER);
				mapMod->pblock->GetValue(PB_WIDTH,t,width,FOREVER);
				mapMod->pblock->GetValue(PB_HEIGHT,t,height,FOREVER);
				mapMod->pblock->GetValue(PB_CAP,t,cap,FOREVER);
				mapMod->pblock->GetValue(PB_CHANNEL,t,channel,FOREVER);	
				mapMod->pblock->GetValue(PB_AXIS,t,axis, FOREVER);




#if 0
				// JOSE'S CODE
				Matrix3 nodeTM, orgTM;
				AffineParts inparts, outparts, gizmoparts;
				orgTM = node->GetNodeTM(0);
				nodeTM = orgTM;
				decomp_affine(orgTM, &inparts);
				mapMod->tmControl->GetValue(t,&nodeTM,FOREVER,CTRL_RELATIVE);
				decomp_affine(nodeTM,&gizmoparts);
				tm = Inverse(orgTM) * nodeTM;
				Point3 p1, p2, plocal;
				p1 = orgTM.GetRow(3);
				p2 = tm.GetRow(3);
				plocal = p2 - p1;
				tm.SetRow(3, plocal);
				decomp_affine(tm, &outparts);
				
#else
				//JERRY'S CODE
				Matrix3 nodeTM(1), orgTM(1);
				orgTM = node->GetNodeTM(0);
				mapMod->tmControl->GetValue(t,&nodeTM,FOREVER,CTRL_RELATIVE);
				tm = Inverse(orgTM) * nodeTM;
#endif



			}
		}
		object = derivedObject->GetObjRef();
		if(object == NULL)
		{
			multipleDerived = 1;
		}
		else 
		{
			objectSID = object->SuperClassID();
		}
	}
}

void Textparts::putNode(INode *node, Interface *ip)  // must add section to make new modifier.
{
	Object *object, *orgObject;
	IDerivedObject *derivedObj;
	SClass_ID sID;
	Class_ID cID;
	Modifier *genericModifier;
	MapMod *mapMod;
	ModContext *mc;
	TimeValue t = 0;
	int hasMapping = 0;
	Interval valid = FOREVER;			// now check for validity
	Interval iv;
	int multipleDerived = 0;
	TSTR nameOfMat(matName); 

	object = node->GetObjectRef();
	orgObject = object;
	MtlBaseLib &matlLib = ip->GetMaterialLibrary();		// get Mat'l library

	int matIndex = matlLib.FindMtlByName(nameOfMat);		// find matching matl name and get the mat index
	if(matIndex != -1)
	{
		MtlBase *matlbase = matlLib[matIndex];				// get matl ptr 
		Mtl *matl = (Mtl*) matlbase;
		node->SetMtl(matl);									// now assign material
		sID = object->SuperClassID();
		//while(sID == GEN_DERIVOB_CLASS_ID)
		while((multipleDerived != 1) && (hasMapping != 1) && (sID == GEN_DERIVOB_CLASS_ID))
		{
			derivedObj = (IDerivedObject*)object;
			int numMods = derivedObj->NumModifiers();
			for(int i=0;i<numMods;i++)
			{
				genericModifier = derivedObj->GetModifier(i);
				cID = genericModifier->ClassID();
				if(cID.PartA() == 0xf72b1 && cID.PartB()==0x00)
				{
					hasMapping = 1;
					ObjectState os(derivedObj);
					mapMod = (MapMod*)genericModifier;
					mc = derivedObj->GetModContext(i);
					mapMod->pblock->SetValue(PB_MAPTYPE,t,type);		// apply ParamBlk values to mapmod.
					mapMod->pblock->SetValue(PB_UTILE,t,utile);
					mapMod->pblock->SetValue(PB_VTILE,t,vtile);
					mapMod->pblock->SetValue(PB_WTILE,t,wtile);
					mapMod->pblock->SetValue(PB_UFLIP,t,uflip);
					mapMod->pblock->SetValue(PB_VFLIP,t,vflip);
					mapMod->pblock->SetValue(PB_WFLIP,t,wflip);
					mapMod->pblock->SetValue(PB_LENGTH,t,length);
					mapMod->pblock->SetValue(PB_WIDTH,t,width);
					mapMod->pblock->SetValue(PB_HEIGHT,t,height);
					mapMod->pblock->SetValue(PB_CAP,t,cap);
					mapMod->pblock->SetValue(PB_CHANNEL,t,channel);
					//mapMod->SetAxis(axis);
					// local nodetm stuff
					Matrix3 nodeTM = node->GetNodeTM(0);
					// end local nodetm stuff
					AffineParts inparts, outparts;
	
					Matrix3 data2TM = nodeTM * tm;
				
					SetXFormPacket dataPacket(data2TM);
					mapMod->tmControl->SetValue(t,&dataPacket,1,CTRL_RELATIVE);
					decomp_affine(tm, &inparts);
					Matrix3 outMatrix(1);
					mapMod->tmControl->GetValue(t,&outMatrix,FOREVER,CTRL_RELATIVE);
					decomp_affine(outMatrix,&outparts);
			
					mapMod->ModifyObject(t, *mc, &os, NULL);
					mapMod->NotifyDependents(FOREVER,PART_TEXMAP,REFMSG_CHANGE);
					
				}
			}
			object = derivedObj->GetObjRef();
			if(object == NULL)
			{
				multipleDerived = 1;
			}
			else
			{
				sID = object->SuperClassID();
			}
		}

		if(!hasMapping)		// matching node has no mapping modifier must make new modifier.
		{
			IDerivedObject *newDerObj = CreateDerivedObject(orgObject);
			node->MakeRefByID(FOREVER,1,newDerObj);		// node now references this derived object
			MapMod *newMapping = (MapMod*) ip->CreateInstance(
				OSM_CLASS_ID,
				Class_ID(UVWMAPOSM_CLASS_ID,0));
			newDerObj->AddModifier(newMapping);
			RefResult result = newDerObj->ReferenceObject(orgObject);  // now we reference the editable mesh
			//int modIndex = newDerObj->NumModifiers();
			//for(int i=0;i<modIndex;i++)
			//{
			//	genericModifier = newDerObj->GetModifier(i);
			//	cID = genericModifier->ClassID();
			//	if(cID.PartA() == 0xf72b1 && cID.PartB()==0x00)
			//	{
					mc = newDerObj->GetModContext(0);
			//	}
			//}
			newMapping->InitControl(*mc,orgObject,MAP_PLANAR,t);
			newMapping->pblock->SetValue(PB_MAPTYPE,t,type);		// apply ParamBlk values to mapmod.
			newMapping->pblock->SetValue(PB_UTILE,t,utile);
			newMapping->pblock->SetValue(PB_VTILE,t,vtile);
			newMapping->pblock->SetValue(PB_WTILE,t,wtile);
			newMapping->pblock->SetValue(PB_UFLIP,t,uflip);
			newMapping->pblock->SetValue(PB_VFLIP,t,vflip);
			newMapping->pblock->SetValue(PB_WFLIP,t,wflip);
			newMapping->pblock->SetValue(PB_LENGTH,t,length);
			newMapping->pblock->SetValue(PB_WIDTH,t,width);
			newMapping->pblock->SetValue(PB_HEIGHT,t,height);
			newMapping->pblock->SetValue(PB_CAP,t,cap);
			newMapping->pblock->SetValue(PB_CHANNEL,t,channel);
			newMapping->SetAxis(axis);

			//newMapping->NotifyDependents(FOREVER,PART_TEXMAP,REFMSG_CHANGE);
			ObjectState os2(newDerObj);

			Matrix3 nodeTM = node->GetNodeTM(0);
			Matrix3 data2TM = nodeTM * tm;

			SetXFormPacket dataPacket(data2TM);	
			
			newMapping->tmControl->SetValue(t,&dataPacket,1,CTRL_RELATIVE);
			newMapping->ModifyObject(t, *mc, &os2, NULL);
			newMapping->NotifyDependents(FOREVER,PART_TEXMAP,REFMSG_CHANGE);
		
		}
	}
	else
	{

	}

}

void Textparts::writeNode(ostream &stream)
{
	stream << nodeName << endl;
	stream << matName << endl;
	stream << type << endl;
	stream << uflip << endl;
	stream << vflip << endl;
	stream << wflip << endl;
	stream << cap << endl;
	stream << channel << endl;
	stream << utile << endl;
	stream << vtile << endl;
	stream << wtile << endl;
	stream << length << endl;
	stream << width << endl;
	stream << height << endl;
	stream << axis << endl;
	Point3 row;
	for(int i=0;i<4;i++)
	{
		row = tm.GetRow(i);
		stream << row.x << endl;
		stream << row.y << endl;
		stream << row.z << endl;
	}
	stream << "Node End\n" << endl;
}

int Textparts::readNode(TCHAR *data, long position)
{
	TCHAR *line;
	int stringLen, totalLen;
	stringLen = 0;
	totalLen = 0;
	line = _tcstok(&data[position], "\n");
	_tcscpy(nodeName, line);
	stringLen = _tcslen(line);
	totalLen = totalLen + stringLen + 1; // the +1 is for the newline replaced by the null in
										 // the _tcstok call above.
	line = _tcstok(NULL, "\n");
	_tcscpy(matName, line);
	stringLen = _tcslen(line);
	totalLen = totalLen + stringLen + 1;

	line = _tcstok(NULL, "\n");
	_stscanf(line, "%d",&type);
	stringLen = _tcslen(line);
	totalLen = totalLen + stringLen + 1;

	line = _tcstok(NULL, "\n");
	_stscanf(line, "%d",&uflip);
	stringLen = _tcslen(line);
	totalLen = totalLen + stringLen + 1;
	
	line = _tcstok(NULL, "\n");
	_stscanf(line, "%d",&vflip);
	stringLen = _tcslen(line);
	totalLen = totalLen + stringLen + 1;
	
	line = _tcstok(NULL, "\n");
	_stscanf(line, "%d",&wflip);
	stringLen = _tcslen(line);
	totalLen = totalLen + stringLen + 1;
	
	line = _tcstok(NULL, "\n");
	_stscanf(line, "%d",&cap);
	stringLen = _tcslen(line);
	totalLen = totalLen + stringLen + 1;
	
	line = _tcstok(NULL, "\n");
	_stscanf(line, "%d",&channel);
	stringLen = _tcslen(line);
	totalLen = totalLen + stringLen + 1;
	
	line = _tcstok(NULL, "\n");
	_stscanf(line, "%f",&utile);
	stringLen = _tcslen(line);
	totalLen = totalLen + stringLen + 1;
	
	line = _tcstok(NULL, "\n");
	_stscanf(line, "%f",&vtile);
	stringLen = _tcslen(line);
	totalLen = totalLen + stringLen + 1;
	
	line = _tcstok(NULL, "\n");
	_stscanf(line, "%f",&wtile);
	stringLen = _tcslen(line);
	totalLen = totalLen + stringLen + 1;
	
	line = _tcstok(NULL, "\n");
	_stscanf(line, "%f",&length);
	stringLen = _tcslen(line);
	totalLen = totalLen + stringLen + 1;
	
	line = _tcstok(NULL, "\n");
	_stscanf(line, "%f",&width);
	stringLen = _tcslen(line);
	totalLen = totalLen + stringLen + 1;
	
	line = _tcstok(NULL, "\n");
	_stscanf(line, "%f",&height);
	stringLen = _tcslen(line);
	totalLen = totalLen + stringLen + 1;
	
	line = _tcstok(NULL, "\n");
	_stscanf(line, "%d",&axis);
	stringLen = _tcslen(line);
	totalLen = totalLen + stringLen + 1;

	Point3 row;
	for(int i=0;i<4;i++)
	{
		line = _tcstok(NULL, "\n");
		_stscanf(line, "%f",&(row.x));
		stringLen = _tcslen(line);
		totalLen = totalLen + stringLen + 1;
		
		line = _tcstok(NULL, "\n");
		_stscanf(line, "%f",&(row.y));
		stringLen = _tcslen(line);
		totalLen = totalLen + stringLen + 1;
		
		line = _tcstok(NULL, "\n");
		_stscanf(line, "%f",&(row.z));
		stringLen = _tcslen(line);
		totalLen = totalLen + stringLen + 1;

		tm.SetRow(i,row);
	}
	line = _tcstok(NULL, "\n");
	stringLen = _tcslen(line);
	totalLen = totalLen + stringLen + 1;
	
	if(!_tcscmp(line,"Node End"))	// should have the end of section line
	{
		//line = _tcstok(NULL, "\n");	// eat the last line to move stream pointer.
		//stringLen = _tcslen(line);
		totalLen = totalLen +  1;
		return totalLen;			// Okay.  Return length read.
	}
	else
	{
		return -1;					// Errror!! Return -1
	}
}

//
// =================  Global Functions ======================
//

int GetChildren(int children, INode* base, ofstream &stream);
int FindMatchingNode(Textparts inparts, INode* baseNode, Interface *ip);
int CheckValidity(Textparts inparts, INode* baseNode, Interface *ip);

GetChildren(int children, INode* base, ofstream &stream)
{
	INode	*child;
	int grandChildren=0;
	Textparts child_parts;
	for(int i=0;i<children;i++)
	{
		child = base->GetChildNode(i);
		if(child->SuperClassID()== BASENODE_CLASS_ID)
		{
			child_parts.setNode(child);
			child_parts.writeNode(stream);
			grandChildren = child->NumberOfChildren();
			if(grandChildren) // recursive call to get rest of tree.
			{
				GetChildren(grandChildren,child,stream);
			}
		}
	}
	return grandChildren;
}

int FindMatchingNode(Textparts inparts, INode* baseNode, Interface *ip)
{
	int children;
	int match = 0;
	int i = 0;
	INode* child;
	TCHAR *name;
	name = baseNode->GetName();
	if(!_tcscmp(name,inparts.nodeName))
	{
		match = 1;
		inparts.putNode(baseNode, ip);
	}
	children = baseNode->NumberOfChildren();
	while((!match) && (i<children))
	{
		child = baseNode->GetChildNode(i);
		if(child->SuperClassID()== BASENODE_CLASS_ID)
		{
			match = FindMatchingNode(inparts, child, ip);
		}
		i++;
	}
	return match;
}

int CheckValidity(Textparts inparts, INode* baseNode, Interface *ip)
{
	int children;
	int match = 1;				// match = 1 means no match for material
	int i = 0;
	INode* child;
	TSTR nameOfMat(inparts.matName);

	MtlBaseLib &matLib = ip->GetMaterialLibrary();
	int matIndex = matLib.FindMtlByName(nameOfMat);

	if(matIndex != -1)
	{
		match = 0;
	}
	children = baseNode->NumberOfChildren();
	while((match) && (i<children))
	{
		child = baseNode->GetChildNode(i);
		if(child->SuperClassID()== BASENODE_CLASS_ID)
		{
			match = CheckValidity(inparts, child, ip);
		}
		i++;
	}
	return match;
}


class Poltest : public UtilityObj {
	public:

		IUtil *iu;
		Interface *ip;
		HWND hPanel;
	
		//Mapping parameters
		int type, uflip, vflip, wflip, cap, channel;	
		float utile, vtile, wtile, length, width, height;
		
		// Material Data
		Mtl	*mtl;

		// Mapping Transform Matrix
		Matrix3 orgtm;

		//Constructor/Destructor
		Poltest();
		~Poltest();

		void BeginEditParams(Interface *ip,IUtil *iu);
		void EndEditParams(Interface *ip,IUtil *iu);
		void DeleteThis() {}

		int FindChildren(INode *node);

		void Init(HWND hWnd);
		void Destroy(HWND hWnd);
};



static Poltest thePoltest;

class PoltestClassDesc:public ClassDesc {
	public:
	int 			IsPublic() {return 1;}
	void *			Create(BOOL loading = FALSE) {return &thePoltest;}
	const TCHAR *	ClassName() {return GetString(IDS_CLASS_NAME);}
	SClass_ID		SuperClassID() {return UTILITY_CLASS_ID;}
	Class_ID		ClassID() {return POLTEST_CLASS_ID;}
	const TCHAR* 	Category() {return GetString(IDS_CATEGORY);}
	void			ResetClassParams (BOOL fileReset);

};

static PoltestClassDesc PoltestDesc;
ClassDesc* GetPoltestDesc() {return &PoltestDesc;}

//TODO: Should implement this method to reset the plugin params when Max is reset
void PoltestClassDesc::ResetClassParams (BOOL fileReset) 
{

}

static BOOL CALLBACK PoltestDlgProc(
		HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{	
	TSTR str;
	Matrix3 orgtm(1);
	ofstream outfile;
	ifstream infile;
	Textparts childParts;
	Textparts inParts;
	AffineParts childDecom;
	char szFile[260]={NULL};
	char title_file[50] = {NULL};
	OPENFILENAME ofn;					// common dialog box structure
	INode	*rootNode;
	streampos endOfFile, length;
	int found = 0, valid = 0, totalValid = 0;;
	
	switch (msg) 
	{
		case WM_INITDIALOG:
			thePoltest.Init(hWnd);
			return TRUE;
			break;

		case WM_DESTROY:
			thePoltest.Destroy(hWnd);
			break;

		case WM_COMMAND:
			
			switch (LOWORD(wParam))
			{
				case IDC_ROOTBUTTON:
					rootNode = thePoltest.ip->GetRootNode();
					rootNode->GetClassName(str);
					int		numChildren, success;	

					// Initialize OPENFILENAME
					ZeroMemory(&ofn, sizeof(OPENFILENAME));
					ofn.lStructSize = sizeof(OPENFILENAME);
					ofn.hwndOwner = hWnd;
					ofn.lpstrFile = (char*) szFile;
					ofn.nMaxFile = sizeof(szFile);
					ofn.lpstrFilter = "Polisher Files\0*.pol\0All\0*.*\0\0";
					ofn.lpstrTitle = "Save as Polisher File";
					ofn.nFilterIndex = 0;
					ofn.lpstrFileTitle = (char*) title_file;
					ofn.nMaxFileTitle = sizeof(title_file);
					ofn.lpstrInitialDir = NULL;
					ofn.Flags = OFN_PATHMUSTEXIST | OFN_EXPLORER | OFN_OVERWRITEPROMPT;
					ofn.lpstrDefExt = "pol";
					if (GetSaveFileName(&ofn)==TRUE) 
					{
						outfile.open(szFile);
					}
				
					numChildren = rootNode->NumberOfChildren();
					success = GetChildren(numChildren, rootNode, outfile);
					outfile.close();
					break;

				case IDC_NEWNODEMAP:

					rootNode = thePoltest.ip->GetRootNode();
					TCHAR *indata;
					long position;
					int ok;

					ok = 0;
					position = 0;
					// Initialize OPENFILENAME
					ZeroMemory(&ofn, sizeof(OPENFILENAME));
					ofn.lStructSize = sizeof(OPENFILENAME);
					ofn.hwndOwner = hWnd;
					ofn.lpstrFile = (char*) szFile;
					ofn.nMaxFile = sizeof(szFile);
					ofn.lpstrFilter = "Polisher Files\0*.pol\0All\0*.*\0\0";
					ofn.nFilterIndex = 0;
					ofn.lpstrTitle = "Open Polisher File";
					ofn.lpstrFileTitle = (char*) title_file;
					ofn.nMaxFileTitle = sizeof(title_file);
					ofn.lpstrInitialDir = NULL;
					ofn.Flags = OFN_PATHMUSTEXIST | OFN_EXPLORER;
				
					if (GetOpenFileName(&ofn)==TRUE) 
					{
						infile.open(szFile,ios::in | ios::nocreate);
					}
					infile.seekg(0,ios::end);
					length = infile.tellg();
					long beginning;
					infile.seekg(0,ios::beg);
					beginning = infile.tellg();
					endOfFile = length - beginning;
					found = 0;
					indata = new TCHAR[endOfFile];
					infile.read(indata, endOfFile);
					int charLen;
					charLen = infile.gcount();			// discrepancy with characters read in 
					infile.close();						// and length - beginning
					
					while((position<charLen)&& (!valid))
					{
						ok = inParts.readNode(indata, position);
						position = position + ok;
						valid = CheckValidity(inParts, rootNode, thePoltest.ip);
						totalValid = totalValid + valid;
					}
					if(!totalValid)
					{
						position = 0;
						infile.open(szFile);			// read back new buffer since above 
						infile.seekg(0,ios::beg);		// put in nulls as it made tokens.
						infile.read(indata,endOfFile);
						infile.close();
						while(position<charLen)
						{ 
							found = 0;
							ok = inParts.readNode(indata, position);
							position = position + ok;
							found = FindMatchingNode(inParts, rootNode, thePoltest.ip);
						}
					}
					else
					{
						int result = MessageBox(NULL, 
							"Materials Were Missing!!\nDo you wish load in Library?", 
							"Materials Missing",
							MB_YESNOCANCEL);
						switch(result)
						{
							case IDYES:
								thePoltest.ip->FileOpenMatLib(hWnd);
							case IDNO:
								position = 0;
								infile.open(szFile);			// read back new buffer since above 
								infile.seekg(0,ios::beg);		// put in nulls as it made tokens.
								infile.read(indata,endOfFile);
								infile.close();
								while(position<charLen)
								{ 
									found = 0;
									ok = inParts.readNode(indata, position);
									position = position + ok;
									found = FindMatchingNode(inParts, rootNode, thePoltest.ip);
								}
								break;
							case IDCANCEL:
								break;
						}
					}
					delete [] indata;
					break;

				case IDC_APPLYAGAIN:
					
					TCHAR *indata2;
					long position2;
					int ok2;

					ok2 = 0;
					position2 = 0;
					rootNode = thePoltest.ip->GetRootNode();
					if(szFile[0]!=NULL)
					{
						infile.open(szFile,ios::in | ios::nocreate);
						infile.seekg(0,ios::end);
						long start;
						length = infile.tellg();
						infile.seekg(0,ios::beg);
						start = infile.tellg();
						endOfFile = length - start;
						found = 0 ;

						indata2 = new TCHAR[endOfFile];
						int readLen;
						readLen = infile.gcount();
						infile.close();

						while(position2<readLen)
						{ 
							found = 0;
							ok2 = inParts.readNode(indata2, position2);
							position2 = position2 + ok2;
							found = FindMatchingNode(inParts, rootNode, thePoltest.ip);
						}
					}
					break;
				}
			break;

		case WM_LBUTTONDOWN:
		case WM_LBUTTONUP:
		case WM_MOUSEMOVE:
			thePoltest.ip->RollupMouseMessage(hWnd,msg,wParam,lParam); 
			break;

		default:
			return FALSE;
	}
	return TRUE;
}



//--- Poltest -------------------------------------------------------
Poltest::Poltest()
{
	iu = NULL;
	ip = NULL;	
	hPanel = NULL;
	orgtm.IdentityMatrix();
}

Poltest::~Poltest()
{

}

void Poltest::BeginEditParams(Interface *ip,IUtil *iu) 
{
	this->iu = iu;
	this->ip = ip;
	hPanel = ip->AddRollupPage(
		hInstance,
		MAKEINTRESOURCE(IDD_PANEL),
		PoltestDlgProc,
		GetString(IDS_PARAMS),
		0);
}
	
void Poltest::EndEditParams(Interface *ip,IUtil *iu) 
{
	this->iu = NULL;
	this->ip = NULL;
	ip->DeleteRollupPage(hPanel);
	hPanel = NULL;
}

void Poltest::Init(HWND hWnd)
{
// This is where to find the root node.
}

void Poltest::Destroy(HWND hWnd)
{

}

int Poltest::FindChildren(INode *node)
{
	int childrenOfNode;
	childrenOfNode = node->NumberOfChildren();
	return childrenOfNode;
}