/*
	ZBinaryWriter.hpp
	Author: Patrick Baggett <ptbaggett@762studios.com>
	Created: 3/11/2013

	Purpose: 

	Binary stream writer interface

	License:

	TODO

*/

#pragma once

#ifndef _ZBINARYWRITER_HPP
#define _ZBINARYWRITER_HPP

#include <SST/SST_Endian.h>
#include <pstdint.h>

class ZBinaryWriter
{

	public:
		ZBinaryWriter(SST_ByteOrder streamOrder) :
		streamByteOrder(streamOrder)
		{
		}

		//=====================================================================
		//SINGLE ELEMENT WRITE
		//=====================================================================
		virtual void WriteU8(uint8_t v) = 0;
		virtual void WriteU16(uint16_t v) = 0;
		virtual void WriteU32(uint32_t v) = 0;
		virtual void WriteU64(uint64_t v) = 0;
		void WriteF32(float v) {  WriteU32(cast_f2i(v)); }
		void WriteF64(double v) { WriteU64(cast_d2i(v)); }

		//=====================================================================
		//ARRAY WRITE
		//=====================================================================
		/*
		virtual public ZBinaryWriter::WriteU8Array
	 
		Writes an array of 8-bit unsigned values to the stream.

		@param v - The base of the array
		@param count - Number of elements to write
		@return (void)
		*/
		virtual void WriteU8Array(const uint8_t* v, size_t count) = 0;

		/*
		virtual public ZBinaryWriter::WriteU16Array
	 
		Writes an array of 16-bit unsigned values to the stream.

		@param v - The base of the array
		@param count - Number of elements to write
		@return (void)
		*/
		virtual void WriteU16Array(const uint16_t* v, size_t count) = 0;

		/*
		virtual public ZBinaryWriter::WriteU32Array
	 
		Writes an array of 32-bit unsigned values to the stream.

		@param v - The base of the array
		@param count - Number of elements to write
		@return (void)
		*/
		virtual void WriteU32Array(const uint32_t* v, size_t count) = 0;

		/*
		virtual public ZBinaryWriter::WriteU64Array
	 
		Writes an array of 64-bit unsigned values to the stream.

		@param v - The base of the array
		@param count - Number of elements to write
		@return (void)
		*/
		virtual void WriteU64Array(const uint64_t* v, size_t count) = 0;

		/*
		public ZBinaryWriter::WriteF32Array
	 
		Writes an array of 32-bit floating point values to the stream.

		@param v - The base of the array
		@param count - Number of elements to write
		@return (void)
		*/
		void WriteF32Array(const float* v, size_t count) { WriteU32Array((uint32_t*)v, count); }

		/*
		public ZBinaryWriter::WriteF64Array
	 
		Writes an array of 64-bit floating point values to the stream.

		@param v - The base of the array
		@param count - Number of elements to write
		@return (void)
		*/
		void WriteF64Array(const double* v, size_t count) { WriteU64Array((uint64_t*)v, count); }

		//=====================================================================
		//STREAM SEEKING / POSITIONING
		//=====================================================================
		/*
		virtual public ZBinaryReader::GetOffset
	 
		Gets the current (zero-based) offset into the stream from which the next read will
		be performed.
		
		@return (size_t) - The offset.
		*/
		virtual size_t GetOffset() const = 0;

		/*
		public ZBinaryReader::SeekForward
	 
		Advances the offset into the stream by the given number of bytes.
		No validation is performed.
		
		@param amount - The amount of seek forward by.
		@return (void)
		*/
		void SeekForward(size_t amount) { SeekTo(GetOffset() + amount); }

		/*
		public ZBinaryReader::SeekBackward
	 
		Rewinds the offset into the stream by the given number of bytes.
		No validation is performed.
		
		@param amount - The amount of seek backward by.
		@return (void)
		*/
		void SeekBackward(size_t amount) { SeekTo(GetOffset() - amount); }

		/*
		virtual public ZBinaryReader::SeekTo
	 
		Directly sets the offset into the stream from which reads will occur.
		No validation is performed.
		
		@param offset - The new offset
		@return (void)
		*/
		virtual void SeekTo(size_t offset) = 0;

		/*
		public ZBinaryReader::Rewind
	 
		Sets the offset to the start of the stream
		
		@param offset - The new offset
		@return (void)
		*/
		void Rewind() { SeekTo(0); }

		//=====================================================================
		//TYPED ALIASES
		//=====================================================================
		/*
		public ZBinaryWriter::WriteI8
	 
		Writes a single signed 8-bit value to the stream.
	 
		@param v - value read to write to the stream
		*/
		void WriteI8(int8_t v) { return WriteU8((uint8_t)v); }

		/*
		public ZBinaryWriter::WriteI16
	 
		Writes a single signed 16-bit value to the stream.
	 
		@param v - value read to write to the stream
		*/
		void WriteI16(int16_t v) { return WriteU16((uint16_t)v); }

		/*
		public ZBinaryWriter::WriteI32
	 
		Writes a single signed 32-bit value to the stream.
	 
		@param v - value read to write to the stream
		*/
		void WriteI32(int32_t v) { return WriteU32((uint32_t)v); }

		/*
		public ZBinaryWriter::WriteI64
	 
		Writes a single signed 64-bit value to the stream.
	 
		@param v - value read to write to the stream
		*/
		void WriteI64(int64_t v) { return WriteU64((uint64_t)v); }

		/*
		public ZBinaryWriter::WriteI8Array
	 
		Writes an array of 8-bit signed values to the stream.

		@param v - The base of the array
		@param count - Number of elements to write
		@return (void)
		*/
		void WriteI8Array(const int8_t* v, size_t count) { return WriteU8Array((const uint8_t*)v, count); }

		/*
		public ZBinaryWriter::WriteI16Array
	 
		Writes an array of 16-bit signed values to the stream.

		@param v - The base of the array
		@param count - Number of elements to write
		@return (void)
		*/
		void WriteI16Array(const int16_t* v, size_t count) { return WriteU16Array((const uint16_t*)v, count); }

		/*
		public ZBinaryWriter::WriteI32Array
	 
		Writes an array of 32-bit signed values to the stream.

		@param v - The base of the array
		@param count - Number of elements to write
		@return (void)
		*/
		void WriteI32Array(const int32_t* v, size_t count) { return WriteU32Array((const uint32_t*)v, count); }

		/*
		public ZBinaryWriter::WriteI64Array
	 
		Writes an array of 64-bit signed values to the stream.

		@param v - The base of the array
		@param count - Number of elements to write
		@return (void)
		*/
		void WriteI64Array(const int64_t* v, size_t count) { return WriteU64Array((const uint64_t*)v, count); }

		//=====================================================================
		//GETTERS / SETTERS
		//=====================================================================
		/*
		public ZBinaryReader::GetStreamByteOrder
		
		Gets the byte order in which the stream (source data) is read as.
		
		@return (SST_ByteOrder) - The byte order
		*/
		SST_ByteOrder GetStreamByteOrder() const { return streamByteOrder; }

		/*
		public ZBinaryReader::SetStreamByteOrder
		
		Sets the byte order in which the stream (source data) is read as.
		
		@param newOrder - The new byte order
		@return (void)
		*/
		void SetStreamByteOrder(SST_ByteOrder newOrder) { streamByteOrder = newOrder; }

	private:
		SST_ByteOrder streamByteOrder;	//The current byte order the stream is being read in.

};

#endif

