#ifndef __IExNativeFileFormat__
#define __IExNativeFileFormat__
/****************************************************************************************

		IExNativeFileFormat.h

		Copyright: (c) 2001 Eovia Corp. All rights reserved.

		IExNativeFileFormat definition                                         

		Author:	Emil
		Date:	9/21/98

		Revision History

		when		who			what & why
		==========	==========	======================================================
		11/25/99	Brice		Added STimeBasedReaderWrapper
		10/19/99	EricB		Added IExNativeFileFormat::ReadComponent() that takes a familySignature.
								I works exactly like the other ReadComponent() methods, but
								it assumes that the familySignature token has already been read from the stream.

*****************************************************************************************/

#if CP_PRAGMA_ONCE
#pragma once
#endif

#include "COMTypes.h"
#include "MCCountedPtrArray.h"
#include "MCStream.h"


//****** Globally Unique Ids *************************************************

MCDEFINE_GUID(IID_IExNativeFileFormat, 0x19876204, 0x51b0, 0x11d2, 0x84, 0xae, 0x0, 0x60, 0x97, 0xb, 0xc5, 0x21);
MCDEFINE_GUID(IID_IExNativeFileFormatStreamContext, 0xad62c71e, 0x6d6a, 0x4708, 0x8d, 0xeb, 0x44, 0xab, 0xec, 0xf6, 0xb8, 0x25);
MCDEFINE_GUID(IID_IExNativeFileFormatStreamIO, 0xf7e819b8, 0xf768, 0x49d8, 0x84, 0xab, 0x55, 0xc, 0x32, 0x58, 0x90, 0xd8);

//****************************************************************************

struct I3DShModule;
struct TMCVersionNumber;
struct IShTokenStream;
struct IShParameterComponent;
struct ITimeBased;
struct TImportInfo;
class TMCString;
class TMCiostream;
struct	I3DShScene;
struct	I3DShTreeElement;
struct  IShTextureMap;



/// \addtogroup ExternalInterface
/// \{


/// The stream context create by the Native File Format
///
struct IExNativeFileFormatStreamContext : public IStreamContext
{
	// ****************************************************************************
	//								GetFileCarraraVersion
	// 
	/// Returns the version number of Carrara that was used to save the file.
	/// 
	virtual const TMCVersionNumber&		GetFileCarraraVersion() const = 0;

	// ****************************************************************************
	//								FindFile
	// 
	/// Find a file from the file path if this one is not found at the given path.
	/// This function will try to relocate the file or in last resort ask the user
	/// to find it.
	/// 
	virtual boolean						FindFile(IMCFile* inOutFile, TMCArray<IDType>& inFileTypes, IDType& inOutPopupSelection) = 0;
	// ****************************************************************************
	//							GetAssociatedSceneAddNoRef
	// 
	/// Get The scene associated with the stream.
	/// 
	virtual I3DShScene*                 GetAssociatedSceneAddNoRef() = 0;
};


struct IExNativeFileFormatStreamIO : public IMCUnknown
{
	// ****************************************************************************
	//	   						EndRead
	// 
	/// This function is called after everything in the scene has been read and transfered
	/// to the 3DDB. It allows, for instance, postcomputation of values that need to have
	/// the scene available.
	/// 
	/// \param streamContext	the context of the stream where the values have been read
	/// 
	virtual MCCOMErr		MCCOMAPI EndRead		(IExNativeFileFormatStreamContext* streamContext) = 0;
};


/// The interface of the Native (Carrara file format) import/export.
///
struct IExNativeFileFormat : public IMCUnknown   
{
	// ****************************************************************************
	//								ReadComponent
	// 
	/// Reads a component from a token stream.
	/// 
	/// \param stream     The token stream.
	/// \param component  The component that is created.
	/// 
	virtual MCCOMErr MCCOMAPI ReadComponent(IShTokenStream* stream, IShParameterComponent ** component) = 0;
	
	// ****************************************************************************
	//								ReadComponent
	// 
	/// Reads a component from a token stream. The family ID was already read (not the begin token).
	/// 
	/// \param stream     The token stream.
	/// \param component  The component that is created.
	/// \param familyID   The family ID.
	/// 
	virtual MCCOMErr MCCOMAPI ReadComponent(IShTokenStream* stream, IShParameterComponent ** component, IDType familyID) = 0;
	
	// ****************************************************************************
	//								WriteComponent
	// 
	/// Writes a component to a token stream (file).
	/// 
	/// \param stream     The token stream.
	/// \param component  The component that is created.
	/// 
	virtual MCCOMErr MCCOMAPI WriteComponent(IShTokenStream* stream, IShParameterComponent * component) = 0;

	// ****************************************************************************
	//								ReadComponentData
	// 
	/// Reads a component from a token stream. The family ID and class ID have already been read.
	/// 
	/// \param stream     The token stream.
	/// \param component  The component that is created.
	/// 
	virtual MCCOMErr MCCOMAPI ReadComponentData(IShTokenStream* stream, IShParameterComponent * component) = 0;
	
	// ****************************************************************************
	//								WriteComponentData
	// 
	/// Write the component data.
	/// 
	/// \param stream     The token stream.
	/// \param component  The component.
	/// 
	virtual MCCOMErr MCCOMAPI WriteComponentData(IShTokenStream* stream, IShParameterComponent * component) = 0;

	// ****************************************************************************
	//								ReadTimeBased
	// 
	/// Read a time based from a token stream.
	/// 
	/// \param stream     The token stream.
	/// \param timeBased  The timebased.
	/// 
	virtual MCCOMErr MCCOMAPI ReadTimeBased(IShTokenStream * stream, ITimeBased * timeBased) = 0;
	
	// ****************************************************************************
	//								WriteTimeBased
	// 
	/// Writes a time based to a token stream.
	/// 
	/// \param stream     The token stream.
	/// \param keyword    The keyword that identify the timebased.
	/// \param timeBased  The timebased.
	/// 
	virtual MCCOMErr MCCOMAPI WriteTimeBased(IShTokenStream * stream, IDType keyword, ITimeBased * timeBased) = 0;

	// ****************************************************************************
	//								ReadTextureMap
	// 
	/// Reads a texture map from a token stream.
	/// 
	/// \param stream     The token stream.
	/// \param texture	  The texture that is created.
	/// 
	virtual MCCOMErr MCCOMAPI ReadTextureMap(IShTokenStream* stream, IShTextureMap** texture) = 0;
	
	// ****************************************************************************
	//								WriteTextureMap
	// 
	/// Writes a texture map to a token stream (file).
	/// 
	/// \param stream     The token stream.
	/// \param keyword    The keyword that identify the texture map.
	/// \param texture	  The texture that is created.
	/// 
	virtual MCCOMErr MCCOMAPI WriteTextureMap(IShTokenStream* stream, IDType keyword, IShTextureMap* texture) = 0;

	// ****************************************************************************
	//								ReadHeader
	// 
	/// Reads the header of a file.
	/// 
	/// \param stream       The token stream.
	/// \param modules      The list of modules
	/// \param cameraNames  The list of camera names.
	/// 
	virtual MCCOMErr MCCOMAPI ReadHeader(IShTokenStream * stream, TMCCountedPtrArray<I3DShModule> & modules, TMCPtrArray<TMCString> & cameraNames) = 0;

	// ****************************************************************************
	//								ReadSceneFromStream
	// 
	/// Reads a scene from a token stream.
	/// 
	/// \param scene           The scene that is read.
	/// \param stream          The token stream.
	/// \param fatherTree      A pointer the parent tree under which the scene should be imported..
	/// \param fatherTreeName  The name of the father tree.
	///	\param inAutoPlaceInfo Optional data to position the imported data
	/// 
	virtual MCCOMErr MCCOMAPI ReadSceneFromStream(I3DShScene* scene, TMCiostream* stream, I3DShTreeElement* fatherTree, const TMCString& fatherTreeName, TImportInfo* ioImportInfo= NULL) = 0;

	// ****************************************************************************
	//								StartReadingFile
	// 
	/// Should be called when starting to read a file
	/// Note: use CWhileReadingNativeFF instead
	/// 
	/// 
	virtual MCCOMErr MCCOMAPI StartReadingFile() = 0;
	
	// ****************************************************************************
	//								EndReadingFile
	// 
	/// Should be called at the end of reading a file
	/// Note: use CWhileReadingNativeFF instead
	/// 
	virtual MCCOMErr MCCOMAPI EndReadingFile() = 0;

	// ****************************************************************************
	//								StartWritingFile
	// 
	/// Should be called when starting to write a file
	/// Note: use CWhileWritingNativeFF instead
	/// 
	virtual MCCOMErr MCCOMAPI StartWritingFile() = 0;

	// ****************************************************************************
	//								EndWritingFile
	// 
	/// Should be called at the end of writing a file
	/// Note: use CWhileWritingNativeFF instead
	/// 
	virtual MCCOMErr MCCOMAPI EndWritingFile() = 0;
};

/// \}

/// \addtogroup Data
/// \{

/// This is to help import Ray Dream files
/// So you shouldn't need it.
struct STimeBasedReaderWrapper : public TMCObject
{
	IExNativeFileFormat *fReader;
};

/// \}

// ****************************************************************************
//							CWhileReadingNativeFF	
// 
/// Utility class that can be used to call StartReadingFile and EndReadingFile
/// while reading a file.
///
class CWhileReadingNativeFF : public TMCObject
{
public:
	CWhileReadingNativeFF(IExNativeFileFormat* importer) : fImporter(importer) 
	{
		if (MCVerify(fImporter))
		{
			fImporter->StartReadingFile();
		}
	}

	~CWhileReadingNativeFF()
	{
		if (MCVerify(fImporter))
		{
			fImporter->EndReadingFile();
		}
	}

protected:
	IExNativeFileFormat* fImporter;
};


// ****************************************************************************
//							CWhileWritingNativeFF	
// 
/// Utility class that can be used to call StartWritingFile and EndWritingFile
/// while reading a file.
///
class CWhileWritingNativeFF : public TMCObject
{
public:
	CWhileWritingNativeFF(IExNativeFileFormat* exporter) : fExporter(exporter) 
	{
		if (MCVerify(fExporter))
		{
			fExporter->StartWritingFile();
		}
	}

	~CWhileWritingNativeFF()
	{
		if (MCVerify(fExporter))
		{
			fExporter->EndWritingFile();
		}
	}

protected:
	IExNativeFileFormat* fExporter;
};


#endif

