//-------------------------------------------------------------------------
//
// File:		EditableI.h
// Desc:		Editable interface.
// Author:		memon <memon@inside.org>
//
//-------------------------------------------------------------------------
//	Copyright (c) 2000-2004 Moppi Productions. All Rights Reserved.
//  This file is part of Moppi Demopaja SDK. For conditions of 
//  distribution and use, see the accompanying license.txt file.
//  http://www.demopaja.org
//-------------------------------------------------------------------------

#ifndef __DEMOPAJA_EDITABLEI_H__
#define __DEMOPAJA_EDITABLEI_H__

// forward decl.
namespace Edit {
	class EditableI;
};

#include "DataBlockI.h"
#include "UndoC.h"
#include "FileIO.h"
#include "ClassIDC.h"


namespace Edit {

	//! Base classID.
	const PluginClass::SuperClassIdC		BASECLASS_EDITABLE = PluginClass::SuperClassIdC( 1, 0 );

	//! Editable interface
	/*!	Editable interfaces is used by all the objects which are editable.
		The interface defines set of methods which are used for example by the
		undo-system in Demopaja.
	*/
	class EditableI : public DataBlockI
	{
	public:
		// Creates new datablock. See DataBlockI.
		virtual DataBlockI*			create() = 0;

		//! Creates new datablock, with reference to the original.
		/*! \param pOriginal Pointer to the original editable.
			This method is used by the undo system to create a copy
			of the editable while keeping reference to the original.

			The method restore() is used to restore the data from the
			original copy.
		*/
		virtual DataBlockI*			create( EditableI* pOriginal ) = 0;


		//! Deep copy from a data block.
		/*!	\param pBlock Pointer to datablock of same class to data from.
		
			This method should make a deep copy (that is, copy everything)
			of the instance specified by the argument.

			\code
			Example Implementation
			void
			TGAImportC::copy( EditableI* pEditable )
			{
				TGAImportC* pFile = (TGAImportC*)pBlock;

				m_i32Width = pFile->m_i32Width;
				m_i32Height = pFile->m_i32Height;
				m_i32Bpp = pFile->m_i32Bpp;
				m_sFileName = pFile->m_sFileName;

				// duplicate data
				delete m_pData;
				uint32 ui32DataSize = m_i32Width * m_i32Height * (m_i32Bpp / 8);
				m_pData = new uint8[ui32DataSize];
				memcpy( m_pData, pFile->m_pData, ui32DataSize );
			}
			\endcode
		*/
		virtual void				copy( EditableI* pEditable ) = 0;

		//! Shallow copy of a data block.
		/*!	Restores the local data from the given data block.
			This method is used by the Demopaja undo system to restore data
			from a copy. This method should only do a shallow copy, that is,
			copy the variables which can be changed by the methods in the
			interface of the class.

			For example if a import plugin class should not copy the data,
			but only pointer to the data since there isnt any method in the interface
			which would change the data. If the data can be changed the copy()
			is called automatically by the system.

			Example:
			\code
			void
			TGAImportC::restore( EditableI* pEditable )
			{
				TGAImportC*	pFile = (TGAImportC*)pEditable;

				m_ui32TextureId = pFile->m_ui32TextureId;
				m_pData = pFile->m_pData;
				m_i32Width = pFile->m_i32Width;
				m_i32Height = pFile->m_i32Height;
				m_i32Bpp = pFile->m_i32Bpp;
				m_sFileName = pFile->m_sFileName;
			}

			\endcode

			\see DataBlockI::copy
		*/
		virtual void				restore( EditableI* pEditable ) = 0;

		//! Duplicates editable.
		/*! Makes a duplicate of the editable and returns it.
			The duplicated editable has to be released when it is
			no longer used. The copy() method is used to duplicate
			the data.
		*/
		virtual EditableI*			duplicate();

		//! Clones editable.
		/*! Makes a clone of the editable and returns it.
			The duplicated editable has to be released when it is
			no longer used. The restore() method is used to clone
			the data. Also the reference to the original data is
			saved.

			Used internally, usually from the begin_editing() method.

			\see get_original();
		*/
		virtual EditableI*			clone();

		//! Returns original editable, if the editable is a clone, else returns 0.
		/*!	Every time a editable is cloned a reference to the orginal data
			is saved too. This methods enables to get the pointer to the original
			data. This methods is mainly used to determine if the released
			editable is a clone, hence no data will be released.

			Example usage:
			\code
			TGAImportC::~TGAImportC()
			{
				// Check if this editable is a clone.
				if( get_original() )
					return;		// It's clone, return.
				// Delete data
				delete m_pData;
			}
			\endcode
		*/
		virtual EditableI*					get_original() const;

		//! Returns the base class ID.
		virtual PluginClass::SuperClassIdC		get_base_class_id() const;

		//! Update notify from a connected editable.
		virtual PajaTypes::uint32							update_notify( EditableI* pCaller );

		//! Starts new editing scope, returns current undo.
		/*! \param pUndo Undo object to store the changes.
		
			Begins new undo scope, sets the internal undo object
			to the object given as argument. The default implmentation
			uses clone() method to clone data and pushes the clone to the
			undo restore data queue.

			Implemented by the system. If the class needs to store extra information
			which cannot be stored in the clone() method or a special flag needs to be
			set, override this method, but remember to call this memeber at the beginning
			of the overridden method!
		*/
		virtual UndoC*				begin_editing( UndoC* pUndo );

		//! Ends current editing scope, set return previous undo.
		/*!	The default implementation sets the given undo object as current undo object.
			
			This method is implemented by the system and used internally.

			\see begin_editing
		*/
		virtual void				end_editing( UndoC* pUndo );

		//! Returns current undo.
		/*!	Returns current undo object bind by the last begin_editing() call.
			The return value can be NULL.

			Implemented by the system.
		*/
		virtual UndoC*				get_undo();

		//! Save editable to a Demopaja output stream.
		virtual PajaTypes::uint32	save( FileIO::SaveC* pSave ) = 0;

		//! Load editable from a Demopaja input stream.
		virtual PajaTypes::uint32	load( FileIO::LoadC* pLoad ) = 0;

	protected:
		//! Default constructor.
		EditableI();
		//! Default constructor with reference to the original.
		EditableI( EditableI* m_pOriginal );
		//! Default destructor.
		virtual ~EditableI();

	private:
		EditableI*		m_pOriginal;
		UndoC*			m_pUndo;
		bool			m_bAlive;
	};

};

#endif // __DEMOPAJA_EDITABLEI_H__