///////////////////////////////////////////////////////////////////////////////
/// @file deFileSystem.hpp
///
/// @brief base file system interface header
///
/// @author Lightning
///
/// This file is the intellectual property of Novus Delta, LLC.. Usage of the
/// contents of this file is subject to the Destiny3D Member License which
/// can be found at http://www.destiny3d.com.  Any other usage is prohibited.
///
/// This file is distributed "AS IS" without warranty of any kind.  Novus
/// Delta, LLC. does not guarantee the fitness of the contents of this file
/// for any particular purpose.
///
/// Copyright (C) 2001-2003 Novus Delta, LLC. All Rights Reserved.
///
/// <hr>
///                                 Change History
/// <hr>
///
/// @date Nov 2001
/// @author Lightning
/// @remarks Creation
///
/// @date Dec 2002
/// @author kurifu
/// @remarks File finding handles
///
///////////////////////////////////////////////////////////////////////////////

#ifndef DE_FILESYSTEM_HPP
#define DE_FILESYSTEM_HPP

#include "deGlobalTypes.hpp"

#if defined(DEFILE_DLL_EXPORTS) || defined(DESTINY3D_EXPORT_ALL)
#	define DEFILESYSTEM_API extern "C" DEDLL_EXPORT
#elif defined(DESTINY3D_STATIC_LINK)
#	define DEFILESYSTEM_API extern "C"
#else
#	define DEFILESYSTEM_API extern "C" DEDLL_IMPORT
#endif

#ifdef USING_DESTINY3D
#ifdef _DEBUG
#	ifdef DESTINY3D_STATIC_LINK
#		pragma comment(lib, "deFile_sd")
#	else
#		pragma comment(lib, "deFiled")
#	endif //DESTINY3D_STATIC_LINK
#else
#	ifdef DESTINY3D_STATIC_LINK
#		pragma comment(lib, "deFile_s")
#	else
#		pragma comment(lib, "deFile")
#	endif //DESTINY3D_STATIC_LINK
#endif //_DEBUG
#endif //USING_DESTINY3D


//-------------------------------------------
// Classes Declared
//-------------------------------------------
class IdeFileSystem;
class IdeFSReal;
class IdeFSVirtual;
class IdeFile;
struct deFileProperties;

class IdeFile;
struct deFileProperties;

//-------------------------------------------
// Factory functions
//-------------------------------------------
extern "C"
{
	/// create a "real" filesystem - one that's disk-based through the operating system
	DEFILESYSTEM_API IdeFSReal*		IdeFileSystem_CreateFSReal();
	/// create a "virtual" filesystem - one that exists within another file
	DEFILESYSTEM_API IdeFSVirtual*	IdeFileSystem_CreateFSVirtual();
}

//-------------------------------------------
// Defines
//-------------------------------------------

// get rid of the annoying diamond-inheritance warning
#pragma warning (disable : 4250)

//a callback procedure used during move or copying of files to tell of the status
typedef DWORD (*deFSPROGRESS)(s64 BytesCopied, s64 FileSize, DWORD FileStatus, const char *SourceFile, const char *DestinationFile);

//possible return values of the callback
#define deFSPROGRESS_CONTINUE		0x00000001	//continue the operation in question

#define deFSPROGRESS_CANCEL			0x00000002	//cancel the operation that is happening. If a file is moved, it is erased
												//if a file is copied, the destination file is removed

#define deFSPROGRESS_CANCELCURRENT	0x00000004	//cancel just the current file operation, continue on to the next file. Valid
												//on any command. Current file is handled as if Cancel is passed

#define deFSPROGRESS_QUIET			0x00000010	//stop sending messages

//possible values for the file status in the callback
#define deFSCALLBACK_FINISHED		0x00000001	//finished the operation on the specified file

#define deFSCALLBACK_ERROREXISTS	0x00000002	//error occurred due to an existing file or directory. Continue operation or Cancel?
												//cancel will stop the operation completely. Continue will skip the file/directory

#define deFSCALLBACK_ERROROPENED	0x00000003	//error occurred due to the specified file currently being opened. Continue operation?
												//cancel will stop the operation completely. Continue will skip the file/directory

#define deFSCALLBACK_ERRORFATAL		0x00000004	//a fatal error during the operation (probably memory related). The operation WILL be
												//canceled. It is possible for SourceFile and DestinationFile to be null

#define deFSCALLBACK_STARTING		0x00000005	//returned each time a new file has an operation started on it

#define deFSCALLBACK_BLOCKMOVED		0x00000006	//a block of data was moved. If Cancel is returned, the resulting file is removed.
												//if during a move operation, the current file is deleted and no more files are moved.

#define deFSCALLBACK_RECURSE		0x00000007	//should the sub directory be recursed into during a copy? Cancel stops
												//recursive copy, Continue allows it.

//callback returns specific to the VFS
#define deFSCALLBACK_VFSLARGEMOVE	0x00010000	//a file is done moving. the VFS is being shifted to cover the file's original spot
												//FileSize and BytesCopied will represent the total number of bytes and bytes left
												//to move in the VFS

//-------------------------------------------
// Structures
//-------------------------------------------

typedef void* deFSFindHandle;

//-------------------------------------------
// Classes
//-------------------------------------------

/// base interface class for all filesystems.
//class IdeFileSystem : virtual public IdeRefCountBase
DE3D_INTERFACE(IdeFileSystem, IdeRefCountBase)
{
	public:

	protected:
		virtual ~IdeFileSystem() {}
	public:
		///Possible interfaces for the filesystem
		enum interface_t
		{
			iface_IdeFileSystem = 0,
			iface_IdeFSReal,		///Real files
			iface_IdeFSMemory,		///Files stored in memory
			iface_IdeFSVirtual,		///Virtual File System
			iface_force_32bit = 0x7FFFFFFF
		};
		///Function to obtain the proper interface for the filesystem
		///@param[in] i Input for the type of interface to return
		///@return Returns a pointer to the requested interface or NULL if an invalid interface
		virtual void* GetInterface(IdeFileSystem::interface_t i) = 0;

		///Open a file
		///@param[in] Filename Filename to open
		///@param[in] OpenFlags flags for opening the filesystem
		///@arg deFile_Open_Create Create a file, fail if it exists
		///@arg deFile_Open_Existing Open an existing file, fail it if does not exist
		///@arg deFile_Open_Always Always open the file, create if it does not exist or open existing
		///@arg deFile_Open_CreateAlways Always open the file, override if the file already exists
		///@return Return a pointer to an IdeFile class if valid
		virtual IdeFile* Open(const char *Filename, long OpenFlags) = 0;

		///Get the current directoriy
		virtual const char *GetDirectory() = 0;
		///Set the current directory
		virtual deBoolean SetDirectory(const char *Directory) = 0;
		
		///Rename a file
		///@param[in] OldFilename Original file to rename
		///@param[in] NewFilename New name for the file
		///@return True/False if the rename was successful
		virtual	deBoolean Rename(const char *OldFilename, const char *NewFilename) = 0;

		///Delete a file
		///@param[in] Filename File to Delete
		///@param[in] StatusCallback Pointer to a function to call while deleting, pass a NULL for no callbacks
		///@return True/False if the delete was successful
		virtual deBoolean Delete(const char *Filename, deFSPROGRESS StatusCallback) = 0;

		///Move a file
		///@param[in] Filename File to move
		///@param[in] StatusCallback Pointer to a function to call while moving, pass a NULL for no callbacks
		///@return True/False if the move was successful
		virtual deBoolean Move(const char *OldFilename, const char *NewFilename, deFSPROGRESS StatusCallback) = 0;

		///Copy a file
		///@param[in] Filename File to copy
		///@param[in] StatusCallback Pointer to a function to call while copying, pass a NULL for no callbacks
		///@return True/False if the copy was successful
		virtual deBoolean Copy(const char *OldFilename, const char *NewFilename, deFSPROGRESS StatusCallback) = 0;

		///Create a directory
		///@param[in] Directory The name of the directory
		virtual deBoolean AddDirectory(const char *Directory) = 0;

		///Delete a directory
		///@param[in] Name of the directory to delete
		///@param[in] StatusCallback Pointer to a function to call while deleting, pass a NULL for no callbacks
		///@return True/False if the delete was successful
		virtual deBoolean DeleteDirectory(const char *Directory, deFSPROGRESS StatusCallback) = 0;

		///Start a find on the filesystem
		///@param[in] Pattern Pattern to match the files to. ? to match 1 character, * for multiple character matching
		///@param[out] Properties Information about the first file found that matches
		///@return A value used to identify the find for later finds
		virtual void* FindFirst(const char *Pattern, deFileProperties *Properties) = 0;

		///Find the next file in the list that matches
		///@param[in] Handle Value returned by FindFirst
		///@param[out] Properties Information about the file found that matches
		///@return True if a file was found, False if no more files exist
		virtual deBoolean FindNext(void* Handle, deFileProperties *Properties) = 0;

		///Finish a find and cleanup any memory usage
		///@param[in] Handle Find to finish
		///@return True if the find is done, False if there was a problem
		virtual deBoolean FindEnd(void* Handle) = 0;

};

/// class for the real FS.
/// Related functions: IdeFileSystem_CreateFSReal.
/// Related classes: IdeFileReal
//class IdeFSReal : virtual public IdeFileSystem
DE3D_INTERFACE(IdeFSReal, IdeFileSystem)
{
	protected:
		~IdeFSReal() {}
};

/// class for the virtual fs.
/// Related functions: IdeFileSystem_CreateFSVirtual.
/// Related classes: IdeFileVirtual.
//class IdeFSVirtual : virtual public IdeFileSystem
DE3D_INTERFACE(IdeFSVirtual, IdeFileSystem)
{
	protected:
		~IdeFSVirtual() {}

	public:

		//functions to open/close the base file
		virtual deBoolean OpenBaseFile(IdeFile *BaseFile, long OpenFlags) = 0;
		virtual deBoolean OpenBaseFilename(const char *Filename, long OpenFlags) = 0;
		virtual deBoolean CloseBaseFile() = 0;
};



#endif
