#ifndef ICONVAR_H
#define ICONVAR_H

//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
class IConVar;
class CCommand;

//-----------------------------------------------------------------------------
// Command to ConVars and ConCommands
//-----------------------------------------------------------------------------
// ConVar systems
#define FCVAR_NONE                   0	// The default, no flags at all
#define FCVAR_UNREGISTERED      (1<<0)	// If this is set, don't add to linked list, etc.
#define FCVAR_DEVELOPMENTONLY   (1<<1)	// Hidden in released products. Flag is removed automatically if ALLOW_DEVELOPMENT_CVARS is defined.
#define FCVAR_GAMEDLL           (1<<2)	// defined by the game DLL
#define FCVAR_CLIENTDLL         (1<<3)	// defined by the client DLL
#define FCVAR_HIDDEN            (1<<4)	// Hidden. Doesn't appear in find or auto complete. Like DEVELOPMENTONLY, but can't be compiled out.

// ConVar only
#define FCVAR_PROTECTED         (1<<5)	// It's a server cvar, but we don't send the data since it's a password, etc.  Sends 1 if it's not bland/zero, 0 otherwise as value
#define FCVAR_SPONLY            (1<<6)	// This cvar cannot be changed by clients connected to a multiplayer server.
#define	FCVAR_ARCHIVE           (1<<7)	// set to cause it to be saved to vars.rc
#define	FCVAR_NOTIFY            (1<<8)	// notifies players when changed
#define	FCVAR_USERINFO          (1<<9)	// changes the client's info string

#define FCVAR_PRINTABLEONLY     (1<<10)	// This cvar's string cannot contain unprintable characters ( e.g., used for player name etc ).

#define FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS        (1<<10)  // When on concommands this allows remote clients to execute this cmd on the server. 
														 // We are changing the default behavior of concommands to disallow execution by remote clients without
														 // this flag due to the number existing concommands that can lag or crash the server when clients abuse them.

#define FCVAR_UNLOGGED          (1<<11)  // If this is a FCVAR_SERVER, don't log changes to the log file / console if we are creating a log
#define FCVAR_NEVER_AS_STRING   (1<<12)  // never try to print that cvar

// It's a ConVar that's shared between the client and the server.
// At signon, the values of all such ConVars are sent from the server to the client (skipped for local client, of course )
// If a change is requested it must come from the console (i.e., no remote client changes)
// If a value is changed while a server is active, it's replicated to all connected clients
#define FCVAR_REPLICATED        (1<<13)	// server setting enforced on clients, TODO rename to FCAR_SERVER at some time
#define FCVAR_CHEAT             (1<<14)	// Only usable in singleplayer / debug / multiplayer & sv_cheats
#define FCVAR_SS                (1<<15)	// causes varnameN where N == 2 through max splitscreen slots for mod to be autogenerated
#define FCVAR_DEMO              (1<<16)	// record this cvar when starting a demo file
#define FCVAR_DONTRECORD        (1<<17)	// don't record these command in demofiles
#define FCVAR_SS_ADDED          (1<<18)	// This is one of the "added" FCVAR_SS variables for the splitscreen players
#define FCVAR_RELEASE           (1<<19)	// Cvars tagged with this are the only cvars available to customers
#define FCVAR_RELOAD_MATERIALS  (1<<20)	// If this cvar changes, it forces a material reload
#define FCVAR_RELOAD_TEXTURES   (1<<21)	// If this cvar changes, if forces a texture reload

#define FCVAR_NOT_CONNECTED          (1<<22)	// cvar cannot be changed by a client that is connected to a server
#define FCVAR_MATERIAL_SYSTEM_THREAD (1<<23)	// Indicates this cvar is read from the material system thread
#define FCVAR_ARCHIVE_PLAYERPROFILE  (1<<24)	// cvar written to config.cfg on the Xbox

#define FCVAR_SERVER_CAN_EXECUTE    (1<<28)	// the server is allowed to execute this command on clients via ClientCommand/NET_StringCmd/CBaseClientState::ProcessStringCmd.
#define FCVAR_SERVER_CANNOT_QUERY   (1<<29)	// If this is set, then the server is not allowed to query this cvar's value (via IServerPluginHelpers::StartQueryCvarValue).
#define FCVAR_CLIENTCMD_CAN_EXECUTE (1<<30)	// IVEngineClient::ClientCmd is allowed to execute this command.

#define FCVAR_MATERIAL_THREAD_MASK ( FCVAR_RELOAD_MATERIALS | FCVAR_RELOAD_TEXTURES | FCVAR_MATERIAL_SYSTEM_THREAD )
/*
class ConVar : ConCommandBase, IConVar; [MI] (#classinformer)
dq offset ? ? _R4ConVar@@6B@; const ConVar::`RTTI Complete Object Locator'

dq offset ??_G__ExceptionPtr@@QEAAPEAXI@Z_0; 0 Index
dq offset sub_1401F9930
dq offset loc_14046FE90
dq offset ConVar__AddFlags
dq offset ConVar__RemoveFlags
dq offset sub_14046FEA0
dq offset loc_14046FF70
dq offset ConVar__GetHelpString
dq offset sub_14046FEC0
dq offset sub_14046FEE0
dq offset ConVar__IsRegistered
dq offset ConVar__GetDllIdentifier
dq offset sub_14046F3F0
dq offset sub_14046F470
dq offset ConVar__InternalSetFloatValue; The one below also does something similar
dq offset sub_140470340
dq offset sub_140470420; Seems to be InternalSetInt below maybe ?
dq offset sub_140470510
dq offset nullsub
dq offset sub_140470300
dq offset sub_1404701A0
dq offset RegisterConVar; #STR: "Convar '%s' is flagged as both FCVAR_ARCHIVE and FCVAR_ARC
*/

//-----------------------------------------------------------------------------
// Called when a ConCommand needs to execute
//-----------------------------------------------------------------------------
typedef void (*FnCommandCallbackV1_t)(void);
typedef void (*FnCommandCallback_t)(const CCommand& command);

#define COMMAND_COMPLETION_MAXITEMS		128
#define COMMAND_COMPLETION_ITEM_LENGTH	128

#define COMMAND_COMPLETION_MARKER -1

//-----------------------------------------------------------------------------
// Returns 0 to COMMAND_COMPLETION_MAXITEMS worth of completion strings
//-----------------------------------------------------------------------------
typedef int  (*FnCommandCompletionCallback)(const char* partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH]);

//-----------------------------------------------------------------------------
// Interface version
//-----------------------------------------------------------------------------
class ICommandCallback
{
public:
	virtual void CommandCallback(const CCommand& command) = 0;
};

class ICommandCompletionCallback
{
public:
	//virtual int  CommandCompletionCallback(const char* pPartial, CUtlVector< CUtlString > &commands) = 0;
};

//-----------------------------------------------------------------------------
// Called when a ConVar changes value
// NOTE: For FCVAR_NEVER_AS_STRING ConVars, pOldValue == NULL
//-----------------------------------------------------------------------------
typedef void (*FnChangeCallback_t)(IConVar* var, const char* pOldValue, float flOldValue);


//-----------------------------------------------------------------------------
// Abstract interface for ConVars
//-----------------------------------------------------------------------------
abstract_class IConVar
{
public:
	virtual ~IConVar() { };

	// Value set
	virtual void SetValue(const char* pValue) = 0;
	virtual void SetValue(float flValue) = 0;
	virtual void SetValue(int nValue) = 0;

	// Original name 'GetName'. Renamed due to name ambiguity
	// as we are not implementing it in ConVar, we are just
	// interfacing it with the game executable.
	virtual const char* GetCommandName(void) const = 0;

	// Return name of command (usually == GetName(), except in case of FCVAR_SS_ADDED vars
	virtual const char* GetBaseName(void) const = 0;

	// Accessors.. not as efficient as using GetState()/GetInfo()
	// if you call these methods multiple times on the same IConVar
	virtual bool IsConVarFlagSet(int nFlag) const = 0; // Original name 'IsFlagSet'. Renamed for same reason as 'GetName'.

	virtual int GetSplitScreenPlayerSlot() const = 0;
};

struct ConVarFlagsToString_t
{
	int m_nFlag;
	const char* m_pszDesc;
};

inline ConVarFlagsToString_t g_PrintConVarFlags[] =
{
	{ FCVAR_NONE, "none" },
	{ FCVAR_UNREGISTERED, "unregistered" },
	{ FCVAR_DEVELOPMENTONLY, "development_only" },
	{ FCVAR_GAMEDLL, "game" },
	{ FCVAR_CLIENTDLL, "client" },
	{ FCVAR_HIDDEN, "hidden" },
	{ FCVAR_PROTECTED, "protected" },
	{ FCVAR_SPONLY, "singleplayer" },
	{ FCVAR_ARCHIVE, "archive" },
	{ FCVAR_NOTIFY, "notify" },
	{ FCVAR_USERINFO, "userinfo" },
	{ FCVAR_PRINTABLEONLY, "printable_only" },
	{ FCVAR_UNLOGGED, "unlogged" },
	{ FCVAR_NEVER_AS_STRING, "never_as_string" },
	{ FCVAR_REPLICATED, "replicated" },
	{ FCVAR_CHEAT, "cheat" },
	{ FCVAR_SS, "splitscreen" },
	{ FCVAR_DEMO, "demo" },
	{ FCVAR_DONTRECORD, "dont_record" },
	{ FCVAR_SS_ADDED, "splitscreen_added" },
	{ FCVAR_RELEASE, "release" },
	{ FCVAR_RELOAD_MATERIALS, "reload_materials" },
	{ FCVAR_RELOAD_TEXTURES, "reload_textures" },
	{ FCVAR_NOT_CONNECTED, "not_connected" },
	{ FCVAR_MATERIAL_SYSTEM_THREAD, "materialsystem_thread" },
	{ FCVAR_ARCHIVE_PLAYERPROFILE, "playerprofile" },
	{ FCVAR_SERVER_CAN_EXECUTE, "server_can_execute" },
	{ FCVAR_SERVER_CANNOT_QUERY, "server_cannot_query" },
	{ FCVAR_CLIENTCMD_CAN_EXECUTE, "clientcmd_can_execute" },
};

#endif // ICONVAR_H
