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

		IMCFile.h

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

		Author:	tsh
		Date:	9/20/98

		File COM interface

		Revision History

		when		who			what & why
		==========	==========	======================================================
		11/29/99	Arnaud		Added SetExtension.
		2/2/98		Eml			Added SetBaseName/GetBaseName
		10/18/98	tsh			remove SetFileCreator, add GetFreeSpace
		10/16/98	tsh			added SetFileInfo

*****************************************************************************************/
#ifndef __IMCFILE__
#define __IMCFILE__

#if CP_PRAGMA_ONCE
#pragma once
#endif

#include "MCCompObj.h"
#include "MCBasicDefines.h"
#include "MCBasicTypes.h"
#include "MCDateTime.h"


class TMCString;

//*********************** Globally Unique Ids ********************************
MCDEFINE_GUID_H(IID_IMCFile);
MCDEFINE_GUID_H(IID_IMCFileIterator);
//****************************************************************************

/// \addtogroup MCCore
/// \{

/// The application keeps some information about the kind of files it knows something about.
/// Every such kind (like "Text files") is identified by a four bytes constant of type MCFileTypeID.
///
typedef IDType MCFileTypeID;

/// On the mac stores the file's type. Unused on the pc
/// 
struct TMCFileID : public TMCObject
{
	IDType fID;

	TMCFileID()								{ fID= 0; }
	explicit TMCFileID(IDType inMacType)	{ fID= inMacType; }
};

/// \}

/******************************************************************************\
*                                                                              *
*           APIFileInfo                                                        *
*                                                                              *
*           Information about a file                                           *
*                                                                              *
\******************************************************************************/

struct APIFileInfo : public TMCObject
{
	boolean					fIsDir;
	boolean					fIsReadOnly;
	boolean					fIsHidden;
	boolean					fIsResourceFork;

	TMCSystemTime			fCreationTime;
	TMCSystemTime			fModificationTime;

	uint64					fDataSize;
	uint64					fRsrcSize;

	TMCFileID				fType;		//the platform type (for os9, used if there is no exception on osx, ignored on pc)
	IDType					fCreator;	//mac concept
	
	APIFileInfo()
	{
		fIsDir			= false;
		fIsReadOnly		= false;
		fIsHidden		= false;
		fIsResourceFork	= false;		
		fDataSize		= 0;
		fRsrcSize		= 0;		
		fCreator		= 0;
		//fType				has default constructor
		//fCreationTime		has default constructor
		//fModificationTime has default constructor
	}
};



/******************************************************************************\
*                                                                              *
*           IMCFile                                                            *
*                                                                              *
\******************************************************************************/

/// \addtogroup MCCore
/// \{

/// IMCFile is the interface to access a file.
///
/// To create an IMCFile, use  IShFileUtilities::CreateIMCFile():
///
/// \code
///
/// TMCCountedPtr<IMCFile> file;
/// gFileUtilities->CreateIMCFile(&file);
///
/// \endcode
///
struct IMCFile : public IMCUnknown
{
	enum EFileSeekType
	{
		eBegin,
		eCurrent,
		eEnd
	};

	enum EFilePermission 
	{ 
		eRead		= 1,
		eWrite		= 2,
		eReadWrite	= 3,
		eAlways
	};

	enum EFileSeparator
	{ 
		kFileTypeSeparator = ';'
	};

	// ****************************************************************************
	//								SetWithPathName
	// 
	/// Sets the full path name (path of the folder).
	/// 
	/// \param aFileName    The full path name of the folder.
	/// \param isDirectory  True if the file is a directory.    
	/// 
	virtual MCErr	MCCOMAPI SetWithPathName		(const TMCString& aFileName, boolean isDirectory=false) = 0;
	
	// ****************************************************************************
	//								SetWithFullPathName
	// 
	/// Sets the full path name of the file.
	/// 
	/// \param aFileName    The full path name of the file.
	/// \param isDirectory  True if the file is a directory.    
	/// 
	virtual MCErr	MCCOMAPI SetWithFullPathName	(const TMCString& aFileName, boolean isDirectory=false) = 0;
	
	// ****************************************************************************
	//								SetWithFile
	// 
	/// Sets the file path from another file.
	/// 
	/// \param aFile  The file from which we get the path.
	/// 
	virtual MCErr	MCCOMAPI SetWithFile			(const IMCFile& aFile) = 0;

	// ****************************************************************************
	//								SetPermissions
	// 
	/// Sets the read/write permission for this file.
	/// 
	/// \param dataPermission  The permissions (see EFilePermission).
	/// 
	virtual MCErr	MCCOMAPI SetPermissions			(EFilePermission dataPermission) = 0; 

	// ****************************************************************************
	//								Exists
	// 
	/// Returns true if the file exists on the disk.
	/// 
	virtual boolean MCCOMAPI Exists					(void) const = 0;		

	// ****************************************************************************
	//								IsOpen
	// 
	/// Returns true if the file is already opened.
	/// 
	virtual boolean MCCOMAPI IsOpen					(void) const = 0;
	
	// ****************************************************************************
	//								CurrentFileInfo
	// 
	/// Returns information about the file (data of modification...)
	/// 
	virtual void	MCCOMAPI CurrentFileInfo		(APIFileInfo& info) const = 0;
	
	// ****************************************************************************
	//								IsDirectory
	// 
	/// Returns true if the file is a directory.
	/// 
	virtual boolean MCCOMAPI IsDirectory			(void) const = 0;
	
	// ****************************************************************************
	//								GetFileInfo
	// 
	/// Returns information about the file (data of modification...)
	/// 
	virtual MCErr	MCCOMAPI GetFileInfo			(APIFileInfo& info) = 0;
	
	// ****************************************************************************
	//								GetMCFileType
	// 
	/// Returns the file type associated with this file.
	/// 
	virtual MCErr	MCCOMAPI GetMCFileType			(MCFileTypeID& outFileID) const = 0;
	//virtual MCErr	MCCOMAPI GetPlatformFileType	(MCPlatformFileType& fileID) const = 0;
	
	// ****************************************************************************
	//								GetSize
	// 
	/// Returns the size of the file.
	/// 
	/// \param length  The size of the file.
	/// 
	virtual MCErr	MCCOMAPI GetSize				(uint32& length) = 0;	
	virtual MCErr	MCCOMAPI GetPhysicalSize		(uint32& dataSize) = 0;
	
	virtual MCErr	MCCOMAPI GetPosition			(uint32& mark) = 0;
	
	// ****************************************************************************
	//								GetPermissions
	// 
	/// Returns the read/write permissions
	/// 
	virtual void	MCCOMAPI GetPermissions			(EFilePermission& aPermission) const = 0;
	virtual MCErr	MCCOMAPI GetFileFreeSpace		(uint64& freeSpace) = 0;

	// ****************************************************************************
	//								CreateOnDisk
	// 
	/// Creates the file/folder on the disk. (The parent folder must exist)
	/// 
	virtual MCErr MCCOMAPI	CreateOnDisk			(void) = 0;

	// ****************************************************************************
	//								CreateOnDiskWithFullPath
	// 
	/// Creates the file/folder on the disk.
	/// The parent folders are created if needed
	///
	virtual MCErr MCCOMAPI	CreateOnDiskWithFullPath(void) = 0;

	// ****************************************************************************
	//								Remove
	// 
	/// Delete the file from the disk.
	/// 
	virtual MCErr	MCCOMAPI Remove					(void) = 0;
	
	// ****************************************************************************
	//								Open
	// 
	/// Opens a file using the permissions specified in SetPermissions
	/// 
	/// Note: When opening the file to write, the file size is not reset to 0. You
	/// need to call SetEOF for that purpose.
	/// 
	virtual MCErr	MCCOMAPI Open					() = 0;
	
	// ****************************************************************************
	//								Close
	// 
	/// Closes the file.
	/// 
	virtual MCErr	MCCOMAPI Close					(void) = 0;
	

	/// Sets whether the file represents a resource fork and should be opened as such.
	virtual void	MCCOMAPI SetIsResourceFork		(boolean isResourceFork) = 0;

	/// Tells if this file is a resourcefork
	virtual boolean	MCCOMAPI IsResourceFork			(void) const = 0;

	
	// ****************************************************************************
	//								Flush
	// 
	/// Writes all the data to the disk.
	/// 
	virtual MCErr	MCCOMAPI Flush					(void) = 0;
	
	// ****************************************************************************
	//								Rename
	// 
	/// Renames the file.
	/// 
	/// \param newName  The new name of the file.
	/// 
	virtual MCErr	MCCOMAPI Rename					(const TMCString& newName) = 0;

	virtual MCErr	MCCOMAPI Read					(void* buffer, uint32 readAmount, uint32* bytesRead=nil) = 0;
	virtual MCErr	MCCOMAPI Write					(const void* buffer, uint32 writeAmount, uint32* bytesWritten=nil) = 0;
	virtual MCErr	MCCOMAPI Seek					(int32 distance, EFileSeekType startPoint) = 0;	 
	virtual MCErr	MCCOMAPI SetEOF					(uint32 newLength) = 0;  

	//File and PathName support
	virtual void	MCCOMAPI GetFileName			(TMCString& pathName) const = 0;
	virtual void	MCCOMAPI GetPathName			(TMCString& pathName) const = 0;
	virtual void	MCCOMAPI GetFileFullPathName	(TMCString& pathName) const = 0; //PathName+FileName  

	// ****************************************************************************
	//								GetFileURL
	// 
	/// Returns fullpathname as a file URL (file://...)
	/// 
	/// \param outURL  The URL that is returned.
	/// 
	virtual void 	MCCOMAPI GetFileURL				(TMCString& outURL	) const = 0;
	
	// ****************************************************************************
	//								GetUnixFullPathName
	// 
	/// Returns fullpathname as a unix file path (MACOSX only)
	/// 
	/// \param outUnixPathName  The unix path for the file.
	/// 
	virtual void 	MCCOMAPI GetUnixFullPathName	(TMCString& outUnixPathName) const = 0;
	
	// ****************************************************************************
	//								GetParentFolderPath
	// 
	/// Returns the path of the folder containing this file (or folder)
	/// If endBySeparator is true, the last char of the string is the path separator
	///
	/// \param outParentPath  
	/// 
	virtual void	MCCOMAPI GetParentFolderPath	(TMCString& outParentPath) const = 0;

	// ****************************************************************************
	//								GetBaseName
	// 
	/// Returns the base name of the file, ie the file name without any extension.
	/// 
	/// \param baseName  
	/// 
	virtual void	MCCOMAPI GetBaseName			(TMCString& baseName) const = 0;
	
	// ****************************************************************************
	//								SetBaseName
	// 
	/// Sets the base name of the file, ie the file name without any extension.
	/// 
	/// \param baseName  The new base name of the file.
	/// 
	virtual void	MCCOMAPI SetBaseName			(const TMCString& baseName) = 0;

	// ****************************************************************************
	//								GetRelativeFileName
	// 
	/// Incomplete relative path support: it works only if theRelFileName is in a
	/// subfolder of rootName
	///
	/// Example:
	/// 
	///	   - rootName	  = "C:\EOVIA\CARRARA\"
	///	   - theRelFileName= "C:\EOVIA\CARRARA\EXTENSIONS\PLUGINS" becomes "\EXTENSIONS\PLUGINS"
	///
	/// However:
	///	   - theRelFileName= "C:\PROGRAM FILES\" is unchanged
	/// 
	/// \param theRelFileName  The path to make "relative" to rootName
	/// \param rootName        The base path to remove from theRelFileName
	/// 
	virtual void	MCCOMAPI GetRelativeFileName	(TMCString& theRelFileName, const TMCString& rootName) = 0;		

	virtual void	MCCOMAPI SetWithRelativeFileName(const TMCString& theRelFileName, const TMCString& rootName,
													 boolean isDirectory=false) = 0;  

// Modify File Attributes
	virtual MCErr	MCCOMAPI SetMCFileType			(const MCFileTypeID& inFileID) = 0;

	virtual void	MCCOMAPI SetReadOnly			(const boolean			inReadOnly) = 0;
	virtual void	MCCOMAPI SetModificationTime	(const TMCSystemTime&	inModificationTime) = 0;

	///Sets the mac file type and creator (unfortunately still needed)
	///A null pointer won't change the info
	virtual void	MCCOMAPI SetMacTypeAndCreator	(const TMCFileID*		inMacType,
													 const IDType*			inMacCreator) = 0;

	virtual MCErr	MCCOMAPI SetExtension			(const TMCString& extension) = 0;
	virtual void	MCCOMAPI GetExtension			(TMCString& extension) const = 0;
	
//Misc
	virtual boolean MCCOMAPI IsSameAs				(const IMCFile& aFile) = 0; 
	virtual MCErr	MCCOMAPI CopyTo					(IMCFile& toFile) = 0; 
	
//Handle to a file (needed for PSHost for photoshop plugins)
	virtual CFileHandleType	MCCOMAPI GetFileHandle()=0; // Handle to the data fork of the file

	// ****************************************************************************
	//								HashSha256
	// 
	/// Copmute a hash of the file content using the SHA256 algorithm.
	/// 
	/// \param hash  	Returned hash digest
	/// 
	virtual MCErr	MCCOMAPI HashSha256				(TMCArray<uint8>& hash) = 0;
};

/// \}

/// \addtogroup MCCore
/// \{

/// Defines an iterator of the a folder and its subfolders. To create such an iterator use :
/// IShFileUtilities::CreateIMCFileIterator()
///
/// It can be used as follows:
///
/// \code
///
/// TMCCountedPtr<IMCFileIterator> iter;
/// gFileUtilities->CreateIMCFileIterator(&iter,TMCString255("C:\MyFolder"),NULL);
///
/// TMCCountedPtr<IMCFile> file;
/// gFileUtilities->CreateIMCFile(&file);
///
/// for (iter.First(file),iter.More();iter.Next(file))
/// {
/// ...
/// }
///
/// \endcode
///
struct IMCFileIterator : public IMCUnknown
{
	// ****************************************************************************
	//								First
	// 
	/// Returns the first file.
	/// 
	/// \param aFile  A pointer to an IMCFile that will contain the first file path.
	/// 
	virtual void 	MCCOMAPI First	(IMCFile* aFile) = 0;
	
	// ****************************************************************************
	//								Next
	// 
	/// Returns the next file.
	/// 
	/// \param aFile  A pointer to an IMCFile that will contain the next file path.
	/// 
	virtual void	MCCOMAPI Next	(IMCFile* aFile) = 0;
	
	// ****************************************************************************
	//								More
	// 
	/// Returns true if there are more files to iterate over.
	/// 
	virtual boolean MCCOMAPI More	(void) = 0;
};

/// \}

#endif