// NodeObject.h: interface for the CNodeObject class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_NODEOBJECT_H__38050511_782B_11D3_9C1F_00609712FBEF__INCLUDED_)
#define AFX_NODEOBJECT_H__38050511_782B_11D3_9C1F_00609712FBEF__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

//////////////////////////////////////////////////////////////////////
// CObject Derivatives
//////////////////////////////////////////////////////////////////////

#include "mw4headers.hpp"
#include "Vehicle.hpp"
#include "stuff\NotationFile.hpp"
#include <ElementRenderer\ElementRenderer.hpp>
#include <ElementRenderer\GroupElement.hpp>
#include <ElementRenderer\ShapeElement.hpp>
#include <ElementRenderer\ListElement.hpp>
#include <ElementRenderer\GridElement.hpp>
#include <ElementRenderer\SwitchElement.hpp>
#include <ElementRenderer\LODElement.hpp>
#include <ElementRenderer\MultiLODElement.hpp>
#include <ElementRenderer\ShapeLODElement.hpp>
#include <MLR\MLR.hpp>
#include <MLR\MLRPrimitiveBase.hpp>

//extern CMapStringToPtr g_mapKeyType;
// These names map to the types in  enum_keytype
static char NAME_KEYTYPE[][30] = {"Unknown","Content Data File","MW4ANIM Animation File","Erf File","Wav File","Float Value","Point3 Value","Targe TGA file","BSP file","OBB file","ABL Script","Boolean Value","Resource file","FGD file","ContentTrack Project","MATERIAL file","String Value","Integer Value","RAW file","BID file","Compost Texture","PNG file"};
enum ENUM_KEYTYPE {KEYTYPE_UNKNOWN,KEYTYPE_NOTE,KEYTYPE_MW4ANIM,KEYTYPE_ERF,KEYTYPE_WAV,KEYTYPE_FLOAT,KEYTYPE_POINT3,KEYTYPE_TGA,KEYTYPE_BSP,KEYTYPE_OBB,KEYTYPE_ABL,KEYTYPE_BOOL,KEYTYPE_RESOURCE,KEYTYPE_FGD,KEYTYPE_PROJECT,KEYTYPE_MATERIAL,KEYTYPE_STRING,KEYTYPE_INT,KEYTYPE_RAW,KEYTYPE_BID,KEYTYPE_COMPOSTTEXTURE,KEYTYPE_PNG,MAX_KEYTYPE};

// TODO: class ids are incomplete
enum {CLASS_CNODEOBJECT,
	CLASS_CNODEDISK,
	CLASS_CNODEDISKDIRECTORY,
	CLASS_CNODEDISKFILE,
	CLASS_CNODEDATA,
	CLASS_CNODEDATAPAGE,
	CLASS_CNODEDATAENTRY,
	CLASS_CNODEDATAVALUE,
	CLASS_CNODEDATAVALUEFLOAT,
	CLASS_CNODEDATAVALUEPOINT3,
	CLASS_CNODEDATAVALUEBOOL,
	CLASS_CNODEDATAVALUESTRING,
	CLASS_CNODEDATAVALUEINT,
	CLASS_CNODEDATAVALUECOMPOSTTEXTURE,
	CLASS_CNODEDATAVALUEFILE,
	CLASS_CNODEDATAVALUEFILEPROJECT,
	CLASS_CNODEDATAVALUEFILEERF,
	CLASS_CNODEDATAVALUEFILEWAV,
	CLASS_CNODEDATAVALUEFILEMW4ANIM,
	CLASS_CNODEDATAVALUEFILETGA,
	CLASS_CNODEDATAVALUEFILEPNG,
	CLASS_CNODEDATAVALUEFILENOTE,
	CLASS_CNODEDATAVALUEFILEBSP,
	CLASS_CNODEDATAVALUEFILEOBB,
	CLASS_CNODEDATAVALUEFILEABL,
	CLASS_CNODEDATAVALUEFILEFGD,
	CLASS_CNODEDATAVALUEFILEMATERIAL,
	CLASS_CNODEDATAVALUEFILERAW,
	CLASS_CNODEDATAVALUEFILEBID,
	CLASS_CNODEDATAVALUEFILERESOURCE,
	CLASS_CNODEDATAVALUEERF,
	CLASS_CNODEDATAVALUEERFGROUPELEMENT,
	CLASS_CNODEDATAVALUEERFLISTELEMENT,
	CLASS_CNODEDATAVALUEERFGRIDELEMENT,
	CLASS_CNODEDATAVALUEERFLODELEMENT,
	CLASS_CNODEDATAVALUEERFSHAPELODELEMENT,
	CLASS_CNODEDATAVALUEERFSHAPEELEMENT,
	CLASS_CNODEDATAVALUEERFSWITCHELEMENT,
	CLASS_CNODEDATAVALUEMLRELEMENT};

// define the Visit flags
#define VISIT_FLAGALL 0xFFFF
#define VISIT_FLAG1 1
#define VISIT_FLAG2 2
#define VISIT_FLAG3 4

// Be careful with variables placment.  Struct members are 4 byte aligned
class CNodeObject// : public CObject  
{
private:
	struct NODELIST
	{
		CNodeObject *pData;
		NODELIST *pNext;
	}*m_pListChildren,*m_pListReferences;
	//CObList m_listChildren;
	//CObList m_listReferences;
	DWORD m_dwVisited;
protected:
	char *m_szName;
	CNodeObject *m_pNodeParent;
	BYTE m_iClassID;
private:
	WORD m_iRefCount;
public:
	bool m_bDirty;
	CMapPtrToPtr m_mapViewHandles;
	CNodeObject(CNodeObject *,CString,CNodeObject * = NULL,CString = "",CString = "");
	virtual ~CNodeObject();

	POSITION GetFirstChild();
	virtual CNodeObject *GetNextChild(POSITION &);
	POSITION AddChild(CNodeObject *);
	CNodeObject *RemoveChild(POSITION pos);
	CNodeObject *GetAt(POSITION);
	virtual int GetName(CString &);
	virtual int GetName(char *,int);
	CString GetNameStr();
	virtual void SetName(const char *);
	virtual HANDLE ViewNode(CTreeCtrl *,HTREEITEM,int);
	CNodeObject *GetParentNode() {return m_pNodeParent;}
	virtual void Update();
	virtual int Paste(CNodeObject *);	// Paste this node and it's children into the dest node
	virtual CNodeObject *Clone(CNodeObject *,CString,CString);
	virtual bool IsFile();
	virtual bool IsDataValue();
	CString GetRootPath();
	//virtual int Rename(CString, CString,bool);	//Rename a structure: New_Name,Old_Name, substring replace

	BYTE GetClassID() {return m_iClassID;}
	CNodeObject *FindChild(CString,bool = false);

	POSITION GetFirstReference();
	CNodeObject *GetNextReference(POSITION &);

	void AddRef(CNodeObject *);
	CNodeObject *RemoveRef(CNodeObject *);
	WORD GetRefCount() {return m_iRefCount;}
	bool SetVisit(DWORD);	//Get a visited flag, returns old value
	bool GetVisit(DWORD);	//Set a visited flag
	void ResetVisit();		//Resets the visited flag
	void ResetVisitAll();	//Recursively reset all visited 

};

//////////////////////////////////////////////////////////////////////
// CNodeObject Derivatives
//////////////////////////////////////////////////////////////////////

class CNodeDiskFile;
class CNodeDiskDirectory;

class CNodeDisk : public CNodeObject
{
protected:
//	CString m_strParentPath;
	bool m_bFound;
	bool m_bLoaded;
public:
	CNodeDisk(CNodeObject *,CString,bool = false);
	virtual ~CNodeDisk();

	CString GetDirectory();
	CString GetPath();
	//CString GetParentPath() {return m_strParentPath;}
	BOOL IsFound() {return m_bFound;}
	BOOL IsLoaded() {return m_bLoaded;}
	void SetLoaded() {m_bLoaded = true;}
	CNodeDiskFile *DiskCopyFile(CString,CString);
	CNodeDiskFile *DiskCopyFile(LPVOID,DWORD,CString);
	CNodeDisk *DiskCreateDirectory(CString);
	//virtual int Rename(CString, CString,bool);	// Move the directory
};

class CNodeDataValue;
class CNodeData : public CNodeObject
{
public:
	CNodeData(CNodeObject *,CString,CNodeObject * = NULL,CString = "",CString = "");
	virtual ~CNodeData();
	static CNodeDataValue *CreateChild(CNodeObject *,int,CString);
};

//////////////////////////////////////////////////////////////////////
// CNodeDisk Derivatives
//////////////////////////////////////////////////////////////////////

class CNodeDiskDirectory : public CNodeDisk
{
protected:
public:
	CNodeDiskDirectory(CNodeObject *,CString);	// Must have path, it then scans that path and completes the Directory tree
	virtual ~CNodeDiskDirectory();
	void SetParentNode(CNodeObject *pNode) {m_pNodeParent = pNode;}  // Only for the root directory node - add to project
};

class CNodeDiskFile : public CNodeDisk
{
public:
	CNodeDiskFile(CNodeObject *,CString);
	virtual ~CNodeDiskFile();
};

//////////////////////////////////////////////////////////////////////
// CNodeData Derivatives
//////////////////////////////////////////////////////////////////////

class CNodeDataPage: public CNodeData
{
public:
	CNodeDataPage(CNodeObject *,Page *,CString,CString,CString,CNodeObject * = NULL,CString = "",CString = "");
	virtual ~CNodeDataPage();
};

class CNodeDataEntry: public CNodeData
{
public:
	CNodeDataEntry(CNodeObject *,Note *,CString,CString,CNodeObject * = NULL,CString = "",CString = "");
	virtual ~CNodeDataEntry();
	virtual void Update();
	virtual int GetName(char *,int);
	BYTE GetKeyValue();
	POSITION GetKeyPos();
};

class CNodeDataValue: public CNodeData
{
protected:
	int m_iKeyType;
public:
	CNodeDataValue(CNodeObject *,CString,CNodeObject * = NULL,CString = "",CString = "");
	virtual ~CNodeDataValue();
	int GetKeyType() {return m_iKeyType;}
	virtual HANDLE ViewNode(CTreeCtrl *,HTREEITEM,int);
	virtual int Paste(CNodeObject *);
};

//////////////////////////////////////////////////////////////////////
// CNodeDataValue Derivatives
//////////////////////////////////////////////////////////////////////

class CNodeDataValueFile: public CNodeDataValue
{
private:
	// TODO: Maybe store the NodeDisk pointers in an array and make m_pNodeDisk a WORD index into that array
	// to make the structure 4 bytes instead of 8 with 3 wasted bytes for alignment
	CNodeDisk *m_pNodeDisk;
	BYTE m_iParentDirs;
public:
	CNodeDataValueFile(CNodeObject *,CString,CNodeObject * = NULL,CString = "",CString = "");
	virtual ~CNodeDataValueFile();
	CNodeDisk *GetNodeDisk() {return m_pNodeDisk;}
	CNodeDisk *SetNodeDisk(CNodeDisk *);
	virtual int UpdateSelf(CNodeObject *);
	virtual int GetName(char *,int);
	virtual int GetName(CString &);
};

class CNodeDataValueFloat: public CNodeDataValue
{
public:
	CNodeDataValueFloat(CNodeObject *,CString,CNodeObject * = NULL,CString = "",CString = "");
	virtual ~CNodeDataValueFloat();

};

class CNodeDataValuePoint3: public CNodeDataValue
{
public:
	CNodeDataValuePoint3(CNodeObject *,CString,CNodeObject * = NULL,CString = "",CString = "");
	virtual ~CNodeDataValuePoint3();

};

class CNodeDataValueBool: public CNodeDataValue
{
public:
	CNodeDataValueBool(CNodeObject *,CString,CNodeObject * = NULL,CString = "",CString = "");
	virtual ~CNodeDataValueBool();

};

class CNodeDataValueString: public CNodeDataValue
{
public:
	CNodeDataValueString(CNodeObject *,CString,CNodeObject * = NULL,CString = "",CString = "");
	virtual ~CNodeDataValueString();

};

class CNodeDataValueInt: public CNodeDataValue
{
public:
	CNodeDataValueInt(CNodeObject *,CString,CNodeObject * = NULL,CString = "",CString = "");
	virtual ~CNodeDataValueInt();

};

class CNodeDataValueCompostTexture: public CNodeDataValue
{
public:
	CNodeDataValueCompostTexture(CNodeObject *,CString,CNodeObject * = NULL,CString = "",CString = "");
	virtual ~CNodeDataValueCompostTexture();

};

class CNodeDataValueERF: public CNodeDataValue
{
protected:
	ElementRenderer::Element *m_pElement;
public:
	static CNodeDataValueERF *CreateChild(CNodeObject *,ElementRenderer::Element *,CString,CString	);
	CNodeDataValueERF(CNodeObject *,ElementRenderer::Element *,CNodeObject * = NULL,CString = "",CString = "");
	virtual ~CNodeDataValueERF();
	ElementRenderer::Element *GetElement() {return m_pElement;}
};

class CNodeDataValueMLRElement: public CNodeDataValue
{
protected:
	MidLevelRenderer::MLRPrimitiveBase *m_pPrimitave;
public:
	CNodeDataValueMLRElement(CNodeObject *,MidLevelRenderer::MLRPrimitiveBase *,CNodeObject * = NULL,CString = "",CString = "");
	virtual ~CNodeDataValueMLRElement();
	MidLevelRenderer::MLRPrimitiveBase *GetPrimitave() {return m_pPrimitave;}
};

//////////////////////////////////////////////////////////////////////
// CNodeDataValueFile Derivatives
//////////////////////////////////////////////////////////////////////

class CNodeDataValueFileDoc;
class CNodeDataValueFileProject : public CNodeDataValueFile
{
protected:
	CNodeDataValueFileDoc *m_pDoc;
public:
	CNodeDataValueFileProject(CNodeDataValueFileDoc *,CString);
	virtual ~CNodeDataValueFileProject();
	CNodeDataValueFileDoc *GetDocument() {return m_pDoc;}
	virtual int UpdateSelf(CNodeObject *);
};

class CNodeDataValueFileERF: public CNodeDataValueFile
{
public:
	CNodeDataValueFileERF(CNodeObject *,CString,CNodeObject * = NULL,CString = "",CString = "");
	virtual ~CNodeDataValueFileERF();
	virtual int UpdateSelf(CNodeObject *);
};

class CNodeDataValueFileWAV: public CNodeDataValueFile
{
public:
	CNodeDataValueFileWAV(CNodeObject *,CString,CNodeObject * = NULL,CString = "",CString = "");
	virtual ~CNodeDataValueFileWAV();
};

class CNodeDataValueFileMW4ANIM: public CNodeDataValueFile
{
public:
	CNodeDataValueFileMW4ANIM(CNodeObject *,CString,CNodeObject * = NULL,CString = "",CString = "");
	virtual ~CNodeDataValueFileMW4ANIM();

};

class CNodeDataValueFileTGA: public CNodeDataValueFile
{
public:
	static CString GetTexturePath();
	static CString FixName(CString,CNodeObject *);

	CNodeDataValueFileTGA(CNodeObject *,CString,CNodeObject * = NULL,CString = "",CString = "");
	virtual ~CNodeDataValueFileTGA();
};

class CNodeDataValueFilePNG: public CNodeDataValueFile
{
public:
	static CString GetTexturePath();
	static CString FixName(CString,CNodeObject *);

	CNodeDataValueFilePNG(CNodeObject *,CString,CNodeObject * = NULL,CString = "",CString = "");
	virtual ~CNodeDataValueFilePNG();
};

class CNodeDataValueFileNote: public CNodeDataValueFile
{
public:
	CNodeDataValueFileNote(CNodeObject *,CString,CNodeObject * = NULL,CString = "",CString = "");
	virtual ~CNodeDataValueFileNote();
	virtual int UpdateSelf(CNodeObject *);
};

class CNodeDataValueFileBSP: public CNodeDataValueFile
{
public:
	CNodeDataValueFileBSP(CNodeObject *,CString,CNodeObject * = NULL,CString = "",CString = "");
	virtual ~CNodeDataValueFileBSP();
};

class CNodeDataValueFileOBB: public CNodeDataValueFile
{
public:
	CNodeDataValueFileOBB(CNodeObject *,CString,CNodeObject * = NULL,CString = "",CString = "");
	virtual ~CNodeDataValueFileOBB();

};

class CNodeDataValueFileABL: public CNodeDataValueFile
{
public:
	CNodeDataValueFileABL(CNodeObject *,CString,CNodeObject * = NULL,CString = "",CString = "");
	virtual ~CNodeDataValueFileABL();

};

class CNodeDataValueFileResource: public CNodeDataValueFile
{
public:
	CNodeDataValueFileResource(CNodeObject *,CString);
	virtual ~CNodeDataValueFileResource();
};


class CNodeDataValueFileFGD: public CNodeDataValueFile
{	
public:
	CString FixName(CString);
	CNodeDataValueFileFGD(CNodeObject *,CString,CNodeObject * = NULL,CString = "",CString = "");
	virtual ~CNodeDataValueFileFGD();

};

class CNodeDataValueFileMATERIAL: public CNodeDataValueFile
{
public:
	CNodeDataValueFileMATERIAL(CNodeObject *,CString,CNodeObject * = NULL,CString = "",CString = "");
	virtual ~CNodeDataValueFileMATERIAL();

};

class CNodeDataValueFileRAW: public CNodeDataValueFile
{
public:
	CNodeDataValueFileRAW(CNodeObject *,CString,CNodeObject * = NULL,CString = "",CString = "");
	virtual ~CNodeDataValueFileRAW();

};

class CNodeDataValueFileBID: public CNodeDataValueFile
{
public:
	CNodeDataValueFileBID(CNodeObject *,CString,CNodeObject * = NULL,CString = "",CString = "");
	virtual ~CNodeDataValueFileBID();

};
//////////////////////////////////////////////////////////////////////
// CNodeDataValueERF Derivatives
//////////////////////////////////////////////////////////////////////

class CNodeDataValueERFGroupElement: public CNodeDataValueERF
{
public:
	CNodeDataValueERFGroupElement(CNodeObject *,ElementRenderer::GroupElement *,CNodeObject * = NULL,CString = "",CString = "");
	virtual ~CNodeDataValueERFGroupElement();
};

class CNodeDataValueERFListElement: public CNodeDataValueERF
{
public:
	CNodeDataValueERFListElement(CNodeObject *,ElementRenderer::ListElement *,CNodeObject * = NULL,CString = "",CString = "");
	virtual ~CNodeDataValueERFListElement();
};

class CNodeDataValueERFGridElement: public CNodeDataValueERF
{
public:
	CNodeDataValueERFGridElement(CNodeObject *,ElementRenderer::GridElement *,CNodeObject * = NULL,CString = "",CString = "");
	virtual ~CNodeDataValueERFGridElement();
};

class CNodeDataValueERFLODElement: public CNodeDataValueERF
{
public:
	CNodeDataValueERFLODElement(CNodeObject *,ElementRenderer::ListElement *,CNodeObject * = NULL,CString = "",CString = "");
	virtual ~CNodeDataValueERFLODElement();
};

class CNodeDataValueERFShapeLODElement: public CNodeDataValueERF
{
public:
	CNodeDataValueERFShapeLODElement(CNodeObject *,ElementRenderer::ShapeLODElement *,CNodeObject * = NULL,CString = "",CString = "");
	virtual ~CNodeDataValueERFShapeLODElement();
};

class CNodeDataValueERFShapeElement: public CNodeDataValueERF
{
public:
	CNodeDataValueERFShapeElement(CNodeObject *,ElementRenderer::ShapeElement *,CNodeObject * = NULL,CString = "",CString = "");
	virtual ~CNodeDataValueERFShapeElement();
};

class CNodeDataValueERFSwitchElement: public CNodeDataValueERF
{
public:
	CNodeDataValueERFSwitchElement(CNodeObject *,ElementRenderer::ListElement *,CNodeObject * = NULL,CString = "",CString = "");
	virtual ~CNodeDataValueERFSwitchElement();
};

#endif // !defined(AFX_NODEOBJECT_H__38050511_782B_11D3_9C1F_00609712FBEF__INCLUDED_)
