// DWBS ------------------------------------------------------------------ DWBS
//
// PLATFORM		: PS2
// PRODUCT		: BIT_DEMON
// VISIBILITY	: PUBLIC
//
// DWBS ------------------------------------------------------------------ DWBS

// PURPOSE: An implementation of the bdStreamBuf class for writing and reading
//			files on a PS2.

#ifndef BD_PS2_FILE_STREAMBUF_H
#define BD_PS2_FILE_STREAMBUF_H

#include <bdCore/bdMemory/bdMemory.h>
#include <bdCore/bdStreams/bdStreambuf.h>

#ifndef BD_PLATFORM_PS2
#error bdPs2FileStreambuf is for PS2 platforms only.
#endif // BD_PLATFORM_PS2

#define BD_PS2_MIN_READ_WRITE_SIZE (512)
#define BD_PS2_FILE_BUFFER_SIZE (BD_PS2_MIN_READ_WRITE_SIZE * 1)

class bdPs2FileStreambuf : public bdStreambuf
{
	public:

		BD_DECLARE_NEW_AND_DELETE_OPERATORS

		/// Supported file opening modes.
		/// READ indicates a file it to be opened for output.
		/// Any existing contents will be erased.
		/// WRITE indicates a file it to be opened for input.
		/// The file must exist.
		/// APPEND indicates a file it to be opened for output. New output
		/// will be appended at the end of the file.
		enum OpenMode
		{
			READ,
			WRITE,
			APPEND
		};

		/// Default constructor
		bdPs2FileStreambuf() {};

		/// Constructor
		bdPs2FileStreambuf(const bdChar8 *const filename,
						   const OpenMode mode);

		/// Virtual destructor
		virtual ~bdPs2FileStreambuf();

	protected:

		/// Pure virtual function overridden from bdStreambuf.
		/// Attempts to read \a nbytes of raw data from the device pointed
		/// to by \a m_handle.
		/// \param dest[out] Put the requested data into this location.
		/// \param nbytes[in] The number of bytes to get from the device.
		/// \return The number bytes actually read.
		/// \note If the return value differs from \a nbytes,
		///  \a END_OF_FILE has been reached.
		virtual bdUInt32 bufGetFrom(bdChar8 *const dest,
									const bdUInt32 nbytes);

		/// Pure virtual function overridden from bdStreambuf.
		/// Attempts to write \a nbytes of raw data from the device pointed
		/// to by \a m_handle.
		/// \param src[out] Get the required data from this location.
		/// \param nbytes[in] The number of bytes to try and write to the device.
		/// \return The number of bytes actually written.
		/// \note If this differs from \a nbytes a \a WRITE_ERROR has occured.
		virtual bdUInt32 bufPutTo(bdChar8 *const src,
								  const bdUInt32 nbytes);

		/// Virtual function overridden from bdStreambuf.
		/// Attempts to set the position indicator for the device pointed
		/// to by \a m_handle.
		/// \param offset[in] The offset to use when seeking.
		/// \param from[in] The place to start seeking.
		/// \return
		///  - True if successful.
		///  - False otherwise.
		virtual bdBool bufSeek(const bdInt32 offset,
							   const SeekFrom from);

		/// Virtual function overridden from bdStreambuf.
		/// Attempts to set \a offset to the current position indicator of the
		/// device pointed to by \a m_handle.
		/// \param offset[out] The offset to set.
		/// \return
		///  - True if successful.
		///  - False otherwise.
		/// \todo Test this.
		virtual bdBool bufTell(bdUInt32 &offset) const;

	protected:

		/// The handle to the file object manipulated by this stream buffer.
		bdInt32 m_handle;

		/// A buffer for reads and writes.
		/// The first half of the buffer is used for reads and the second half
		/// for writes. The buffer is allocated to be 64 byte aligned and should
		/// be a multiple of BD_PS2_MIN_READ_WRITE_SIZE bytes.
		bdChar8 *m_readWritebuffer;

};


#endif // BD_PS2_FILE_STREAMBUF_H
