#if !defined P4OBJECTS_H
#define P4OBJECTS_H

#include "extdll.h" 
#include "decals.h" 

#ifndef UTIL_H
#include "util.h"
#endif

#ifndef MAX_PATH_SIZE
#include "cbase.h" 
#endif

#include "monsters.h" 
#include "weapons.h" 
#include "nodes.h" 
#include "player.h" 
#include "soundent.h" 
#include "shake.h" 
#include "gamerules.h"
#include "strbuf.h"

#include "clientdepotuser.h"
#include "clientapi.h"
#include "ClientDirUser.h"
#include "ClientFileUser.h"
#include "clientluser.h"
#include "FileLogCache.h"
#include "ObjectRev.h"

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

#define MAXRESULTS 130
/*********
 * MAXRESULTS here is unrelated to Perforce's MaxResults setting, although it's a similar concept.
 * It defines the total number of objects that any given "expansion" procedure may create.  It
 * appears that the Half-Life engine crashes if you give it more than about 150 objects to deal
 * with - I've set MAXRESULTS lower than that to account for the entities corresponding to players,
 * weapon projectiles, and other things.  It seems that if you have lots of "other things," such as
 * a large aflock, things go boom, so be careful when designing maps!
 **********/

class CObjectDepot : public CBaseEntity
{ 
	public: 

	void Spawn( ); //Things to do when this object is created.
	void Precache( ); //Models to precache before loading this object into the world.
	void EXPORT Think(); //Called at regular intervals by the engine.
	void EXPORT Touch( CBaseEntity* ); //Called when something touches this object.

	void Long (CBasePlayer*); //The special "green beam" method.
	void Expand (CBasePlayer*); //The special "red beam" method.

	void newLevel(short); //Makes this object rise or descend to a new "level" of expansion.
	void disown(CBaseEntity*); //Remove references to this child object.
	void killKids(CBaseEntity*); //Delete all child objects except this one.

	StrBuf path; //The depot name, ie "depot"
	CBaseEntity* parent; //The parent; this will be a CObjectInfo.
	short level; //The current "level" or altitude.  A level of 1 indicates a currently expanded node.
	ListList dirs; //If expanded, this contains references to all the CObjectDir children.
	ListList files; //Same as above, but references to CObjectFile children.
};

//Most of the P4 objects' methods have similar functions, so I'll omit further description of them except
//where needed.

class CObjectDir : public CBaseEntity  
{
public:
	CObjectDir();
	void Spawn( );
	void Precache( );
	void Think ( );
	void Touch (CBaseEntity* );
	void Long (CBasePlayer*);
	void Expand (CBasePlayer*);
	void newLevel (short);
	void disown (CBaseEntity*);
	void killKids (CBaseEntity*);

	short level;
	CBaseEntity* parent; //The parent of a CObjectDir will be a CObjectDepot or a CObjectDir.
	StrBuf path; //The path is in the form "//depot/main/dir".
	ListList dirs;
	ListList files;
};

class CObjectFile : public CBaseEntity  
{
public:
	void Spawn ( );
	void Precache ( );
	CObjectFile();
	void Think ( );

	void Touch(CBaseEntity*);
	void Long (CBasePlayer*);
	void Expand (CBasePlayer*);
	void newLevel (short);
	void disown(CBaseEntity *);
	void killKids(CBaseEntity *);

	CBaseEntity* parent;
	StrBuf path; //The path is in the form "//depot/main/dir/file".
	short level;

	ListList revs; //This is a list of CObjectRev objects, if this file is expanded.

};

//The CObjectInfo is a CBaseAnimating to allow it to spin.  The other objects could be made
//to spin as well, since their models include spinning animations - I chose not to make this
//be the case, but it'd only require a few extra lines of code to make it happen.

class CObjectInfo : public CBaseAnimating 
{ 
	public: 
	short int level;

	void Spawn( ); 
	void Precache( );
    void EXPORT Think();
	void EXPORT Touch( CBaseEntity* );
	void Expand( CBasePlayer* );
	void newLevel (short);
	void disown (CBaseEntity*);
	void killKids( CBaseEntity *Caller );

	ListList depots;
};

#endif