/*==LICENSE==*

CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011  Cyan Worlds, Inc.

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.

You can contact Cyan Worlds, Inc. by email legal@cyan.com
 or by snail mail at:
      Cyan Worlds, Inc.
      14617 N Newport Hwy
      Mead, WA   99021

*==LICENSE==*/

#ifndef plAnimCmdMsg_inc
#define plAnimCmdMsg_inc

#include "../pnMessage/plMessageWithCallbacks.h"
#include "hsBitVector.h"
#include "hsTemplates.h"
#include "hsGeometry3.h"
#include "../plInterp/plAnimEaseTypes.h"
#include "../plInterp/plAnimTimeConvert.h"

class plAGAnimInstance;

class plAnimCmdMsg : public plMessageWithCallbacks
{
protected:
	char *fAnimName;
	char *fLoopName;

private:
	void IInit() { fBegin=fEnd=fLoopBegin=fLoopEnd=fSpeed=fSpeedChangeRate=fTime=0; fAnimName=fLoopName=nil;}
public:
	plAnimCmdMsg()
		: plMessageWithCallbacks(nil, nil, nil) { IInit(); }
	plAnimCmdMsg(const plKey &s, 
				const plKey &r, 
				const double* t)
		: plMessageWithCallbacks(s, r, t) { IInit(); }
	virtual ~plAnimCmdMsg();

	CLASSNAME_REGISTER( plAnimCmdMsg );
	GETINTERFACE_ANY( plAnimCmdMsg, plMessageWithCallbacks );

	// When adding a command, add a check for it in CmdChangesAnimTime if appropriate
	enum ModCmds
	{
		kContinue=0,
		kStop,
		kSetLooping,
		kUnSetLooping,
		kSetBegin,
		kSetEnd,
		kSetLoopEnd,
		kSetLoopBegin,
		kSetSpeed,
		kGoToTime,
		kSetBackwards,
		kSetForewards,
		kToggleState,
		kAddCallbacks,
		kRemoveCallbacks,
		kGoToBegin,
		kGoToEnd,
		kGoToLoopBegin,
		kGoToLoopEnd,
		kIncrementForward,
		kIncrementBackward,
		kRunForward,
		kRunBackward,
		kPlayToTime,
		kPlayToPercentage,
		kFastForward,
		kGoToPercent,
		kNumCmds,
	};

	hsBitVector		fCmd;

	hsBool Cmd(int n) const { return fCmd.IsBitSet(n); }
	void SetCmd(int n) { fCmd.SetBit(n); }
	void ClearCmd();
	void SetAnimName(const char *name);
	const char *GetAnimName();
	hsBool CmdChangesAnimTime(); // Will this command cause an update to the current anim time?

	void SetLoopName(const char *name);
	const char *GetLoopName();

	hsScalar fBegin;
	hsScalar fEnd;
	hsScalar fLoopEnd;
	hsScalar fLoopBegin;
	hsScalar fSpeed;
	hsScalar fSpeedChangeRate;
	hsScalar fTime;

	// IO
	void Read(hsStream* stream, hsResMgr* mgr);
	void Write(hsStream* stream, hsResMgr* mgr);
};

// plAnimCmdMsg is intented for animation commands sent to a plAnimTimeConvert. Commands that only apply to the
// AG (Animation Graph) system go here.

class plAGCmdMsg : public plMessage
{
protected:
	char *fAnimName;

private:
	void IInit() { fBlend = fAmp = 0;
				   fAnimName=nil;}
public:
	plAGCmdMsg()
		: plMessage(nil, nil, nil) { IInit(); }
	plAGCmdMsg(const plKey &s, 
			   const plKey &r, 
			   const double* t)
		: plMessage(s, r, t) { IInit(); }
	virtual ~plAGCmdMsg();

	CLASSNAME_REGISTER( plAGCmdMsg );
	GETINTERFACE_ANY( plAGCmdMsg, plMessage );

	enum ModCmds
	{
		kSetBlend,
		kSetAmp,
		kSetAnimTime,
	};

	hsBitVector		fCmd;

	hsBool Cmd(int n) const { return fCmd.IsBitSet(n); }
	void SetCmd(int n) { fCmd.SetBit(n); }
	void ClearCmd() { fCmd.Clear(); }
	void SetAnimName(const char *name);
	const char *GetAnimName();

	hsScalar fBlend;
	hsScalar fBlendRate;
	hsScalar fAmp;
	hsScalar fAmpRate;
	hsScalar fAnimTime;

	// IO
	void Read(hsStream* stream, hsResMgr* mgr);
	void Write(hsStream* stream, hsResMgr* mgr);
};

class plAGInstanceCallbackMsg : public plEventCallbackMsg
{
public:
	plAGInstanceCallbackMsg() : plEventCallbackMsg(), fInstance(nil) {}
	plAGInstanceCallbackMsg(plKey receiver, CallbackEvent e, int idx=0, hsScalar t=0, Int16 repeats=-1, UInt16 user=0) :
	  plEventCallbackMsg(receiver, e, idx, t, repeats, user), fInstance(nil) {}

	CLASSNAME_REGISTER( plAGInstanceCallbackMsg );
	GETINTERFACE_ANY( plAGInstanceCallbackMsg, plEventCallbackMsg );

	// These aren't meant to go across the net, so no IO necessary.
	void Read(hsStream* stream, hsResMgr* mgr) {}
	void Write(hsStream* stream, hsResMgr* mgr) {}

	plAGAnimInstance *fInstance;
};

class plAGDetachCallbackMsg : public plEventCallbackMsg
{
protected:
	char *fAnimName;

public:
	plAGDetachCallbackMsg() : plEventCallbackMsg(), fAnimName(nil) {}
	plAGDetachCallbackMsg(plKey receiver, CallbackEvent e, int idx=0, hsScalar t=0, Int16 repeats=-1, UInt16 user=0) :
						  plEventCallbackMsg(receiver, e, idx, t, repeats, user), fAnimName(nil) {}
	virtual ~plAGDetachCallbackMsg();

	CLASSNAME_REGISTER( plAGDetachCallbackMsg );
	GETINTERFACE_ANY( plAGDetachCallbackMsg, plEventCallbackMsg );
	
	// These aren't meant to go across the net, so no IO necessary.
	void Read(hsStream* stream, hsResMgr* mgr) {}
	void Write(hsStream* stream, hsResMgr* mgr) {}
	
	void SetAnimName(const char *name);
	char *GetAnimName();
};


#endif // plAnimCmdMsg_inc