
#ifndef __KEYC_H__
#define __KEYC_H__


#include "DataBlockI.h"
#include "EditableI.h"
#include "UndoC.h"
#include "PajaTypes.h"
#include <vector>
#include "FileIO.h"


namespace Composition {

	//! Maximum number of channels in a key.
	/*!	This cosntant represent the maximum number of channels (values) the
		get_value() method may return. 
	*/
	const PajaTypes::uint32		KEY_MAXCHANNELS = 4;

	//! Key flags.
	enum KeyFlagsE {
		KEY_NOFLAGS =			0,
		KEY_SELECTED =			0x0001,		//!< Key is selected (used only in editor).
		KEY_LINEAR =			0x0002,		//!< Key uses linear interpolation.
		KEY_SMOOTH =			0x0004,		//!< Key uses smooth (TCB spline) interpolation.
		KEY_HOLD =				0x0008,		//!< Key uses hold interpolation.
	};


	//! Keyframe class for controller.
	/*! Key class defines the keys used in controllers. One key can have
		maximum of KEY_MAXCHANNELS channels. Currently the maximum number of
		channels is 4. All the channels in the key are floating point values.

		This class is implemented by the system.
	*/
	class KeyC : public Edit::EditableI
	{
	public:
		//! Create new key with zero no channels.
		static KeyC*				create_new();
		//! Create new key with specified number fo channels.
		static KeyC*				create_new( PajaTypes::int32 i32NumChannels );
		//! Create new key with zero no channels.
		virtual Edit::DataBlockI*	create();
		//! Creates new file handle (used internally), see Edit::EditableI::create().
		virtual Edit::DataBlockI*	create( Edit::EditableI* pOriginal );
		//! Deep copy from a data block, see Edit::DataBlockI::copy().
		virtual void				copy( Edit::DataBlockI* pBlock );
		//! Shallow copy from a editable, see Edit::EditableI::restore().
		virtual void				restore( Edit::EditableI* pEditable );

		//! Returns the time of the key.
		virtual PajaTypes::int32	get_time();
		//! Sets the time of the key.
		virtual void				set_time( PajaTypes::int32 i32Time );

		//! Sets the effect flags.
		/*! Be careful to use this method. There are some flags, which
			have to be in place to make the key work correctly.
			Use add, del or toggle flags methods instead.
		*/
		virtual void				set_flags( PajaTypes::int32 i32Flags );
		//! Sets only specified flags.
		virtual void				add_flags( PajaTypes::int32 i32Flags );
		//! Removes only specified flags.
		virtual void				del_flags( PajaTypes::int32 i32Flags );
		//! Toggles only specified flags.
		virtual void				toggle_flags( PajaTypes::int32 i32Flags );
		//! Returns key flags.
		virtual PajaTypes::int32	get_flags();

		//! Returns ease in value.
		virtual PajaTypes::float32	get_ease_in();
		//! Returns ease out value.
		virtual PajaTypes::float32	get_ease_out();
		//! Returns tension value.
		virtual PajaTypes::float32	get_tens();
		//! Returns continuity value.
		virtual PajaTypes::float32	get_cont();
		//! Returns bias value.
		virtual PajaTypes::float32	get_bias();
		//! Sets ease in value.
		virtual void				set_ease_in( PajaTypes::float32 );
		//! Sets ease out value.
		virtual void				set_ease_out( PajaTypes::float32 );
		//! Sets tension value.
		virtual void				set_tens( PajaTypes::float32 );
		//! Sets continuity value.
		virtual void				set_cont( PajaTypes::float32 );
		//! Sets bias value.
		virtual void				set_bias( PajaTypes::float32 );

		//! Returns the value of the key.
		/*!	If the number of channels of the key isn't absolutely know
			the following method should be used to retrieve the value:

			\code
			float32	f32Values[KEY_MAXCHANNELS];
			pKey->get_value( f32Values );
			\endcode
		*/
		virtual void				get_value( PajaTypes::float32* pValues );
		//! Sets the value of the key.
		/*!	If the number of channels of the key isn't absolutely know
			the following method should be used to set the value:

			\code
			float32	f32Values[KEY_MAXCHANNELS];
			// Set values
			f32Values[0] = 10.0f;
			pKey->set_value( f32Values );
			\endcode
		*/
		virtual void				set_value( const PajaTypes::float32* pValues );

		//! Returns the value of in-coming tangent.
		//! \see get_value
		virtual void				get_in_tan( PajaTypes::float32* pValues );
		//! Sets in-coming tangent.
		//! \see set_value
		virtual void				set_in_tan( const PajaTypes::float32* pValues );

		//! Returns the value of out-going tangent.
		//! \see get_value
		virtual void				get_out_tan( PajaTypes::float32* pValues );
		//! Sets out-going tangent.
		//! \see set_value
		virtual void				set_out_tan( const PajaTypes::float32* pValues );

		//! Serialize the key to a Demopaja output stream.
		virtual PajaTypes::uint32	save( FileIO::SaveC* pSave );
		//! Serialize the key from a Demopaja input stream.
		virtual PajaTypes::uint32	load( FileIO::LoadC* pLoad );

	protected:
		//! Default constructor.
		KeyC();
		//! Creates new key and assign it the specified time.
		KeyC( PajaTypes::int32 i32Time );
		//! Constructor with reference to the original.
		KeyC( Edit::EditableI* pOriginal );
		//! Default destructor.
		virtual ~KeyC();

	private:
		PajaTypes::float32*	m_pValues;
		PajaTypes::int32	m_i32NumChannels;
		PajaTypes::float32	m_f32EaseIn, m_f32EaseOut;
		PajaTypes::float32	m_f32Tens, m_f32Cont, m_f32Bias;
		PajaTypes::int32	m_i32Flags;
		PajaTypes::int32	m_i32Time;
	};

};	// namespace Parameter

#endif // __KEYC_H__
