//===========================================================================//
// File:	filestrm.hpp                                                        //
// Project: MUNGA           Brick: Resource Manager		                    //
// Contents: Implementation Details of resource management                   //
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
//---------------------------------------------------------------------------//
// Copyright (C) 1996, Virtual World Entertainment, Inc.                     //
//                      PROPRIETARY AND CONFIDENTIAL                         //
//===========================================================================//

#pragma once

#include "Stuff.hpp"
#include "MemoryStream.hpp"

namespace Stuff {

	class FileStreamManager;
	class FileStream;

	//##########################################################################
	//##########################    Directory    ###############################
	//##########################################################################

	class Directory
		#if defined(_ARMOR)
			: public Stuff::Signature
		#endif
	{
	public:
		Directory(
			const char *find_files,
			bool find_directories=false
		);
		~Directory();
		
		void TestInstance() const
				{}

		const char* GetCurrentFileName();
		void AdvanceCurrentFile();
		const char* GetCurrentFolderName();
		void AdvanceCurrentFolder();
		const char* GetNewestFile();

	public:
		int  fileOk;

		Stuff::MString currentDirectoryString;

		typedef Stuff::PlugOf<Stuff::MString> DirectoryEntry;
		typedef Stuff::PlugOf<Stuff::MString> DirectoryFolder;

		Stuff::SortedChainOf<DirectoryFolder*, Stuff::MString> folderEntries;
		Stuff::SortedChainOf<DirectoryEntry*, Stuff::MString> fileEntries;
		Stuff::SortedChainIteratorOf<DirectoryFolder*, Stuff::MString> *folderWalker;
		Stuff::SortedChainIteratorOf<DirectoryEntry*, Stuff::MString> *fileWalker;
	};

	//##########################################################################
	//########################    FileStream    ################################
	//##########################################################################

	class FileStream:
		public MemoryStream
	{
		friend class FileStreamManager;

	public:
		static void InitializeClass();
		static void TerminateClass();

		static ClassData *DefaultData;

		static const char *WhiteSpace;
		static HGOSHEAP s_Heap;

		void TestInstance() const;
		static bool TestClass();

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Constructors
	//
	public:
		enum WriteStatus {
			ReadOnly,
			WriteOnly
		};

		FileStream();
		explicit FileStream(
			const char* file_name,
			WriteStatus writable = ReadOnly
		);
		~FileStream();

		void Open(
			const char* file_name = NULL,
			WriteStatus writable = ReadOnly
		);
		void Close();

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Status functions
	//
	public:
		void* GetPointer() const
			{Check_Object(this); Verify(writeEnabled == ReadOnly); return currentPosition;}
		void SetPointer(void *)
			{
				STOP((
				 "No implementation possible for FileStream::SetPointer(void*)"
				));
			}
		void SetPointer(DWORD index);

		MemoryStream& AdvancePointer(DWORD count);
		MemoryStream& RewindPointer(DWORD count);
		MemoryStream& ReadBytes(
			void *ptr,
			DWORD number_of_bytes
		);
		MemoryStream& WriteBytes(
			const void *ptr,
			DWORD number_of_bytes
		);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// File functions
	//
	public:
		virtual bool IsFileOpened();
		const char* GetFileName()
			{Check_Object(this); return fileName;}

		enum SeekType {
			FromBeginning,
			FromEnd
		};

		static char RedirectedName[256];
		static bool IsRedirected;

		static void IgnoreReadOnly(bool flag)
			{IgnoreReadOnlyFlag = flag;}
				

	protected:
		WriteStatus writeEnabled;
		char *fileName;
		HGOSFILE fileHandle;
		bool isOpen;
		static bool IgnoreReadOnlyFlag;
	};

	bool
		CreateDirectories(const char *directories);
}
