/// @file coder.hpp
/// Base Coder class
///
/// @remarks
/// This is the base class from which all coders are derived.
///
/// @author mouser
/// @date   2003.07.29
//---------------------------------------------------------------------------

/// @defgroup Coders Coders
///
/// During compression, the job of the Coder class is use probability
/// information from the modeler to figure out the optimal bitcodes to use
/// when writing symbols into the output stream.  During decompression, the
/// coder is responsible for reading bitcodes from the input and providing
/// a stream of symbol numbers to the compressor.

//---------------------------------------------------------------------------
// forward declarations
class OctaneCoder;
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
// recursive header protection
#ifndef CoderH
#define CoderH
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
// application includes
#include "../bitio/bitio.hpp"
#include "../core/octaneclass.hpp"
#include "../modelers/modeler.hpp"
// system includes
//---------------------------------------------------------------------------




//---------------------------------------------------------------------------
/// During compression, the job of the Coder class is use probability information
///  from the modeler to figure out the optimal bitcodes to use when writing
///  symbols into the output stream.  During decompression, the coder is
///  responsible for reading bitcodes from the input and providing a stream of
///  symbol numbers to the compressor.
///
/// @ingroup Coders
///
class OctaneCoder : public OctaneClass
{
public:
	/// constructor
	OctaneCoder() { ; }
	/// destructor
	virtual ~OctaneCoder() { ; }
public:
	//---------------------------------------------------------------------------
	// OCTANE PUBLIC API - RTTI FUNCTIONS - these are supported by all derived classes
	virtual std::string GetName() {return "OctaneCoder";}
	virtual std::string GetDescription() {return "Base Coder";}
	virtual std::string GetHelpInformation() { return ""; }
	//---------------------------------------------------------------------------
public:
	//---------------------------------------------------------------------------
	// CODER PUBLIC API - PARSING FUNCTIONS
	/// write bits for symbol number
	/// @return true on success
	virtual bool WriteSymbolBits(int symbolnum, bitwriter &bw)=0;
	/// Decode the next symbol from the input
	/// @return true on success, false when there are no more symbols to read.
	virtual bool DecodeSymbolFromInput(int &symbolnum, bitreader &br)=0;
	//---------------------------------------------------------------------------
public:
	//---------------------------------------------------------------------------
	// CODER PUBLIC API - STATE PREPARATION
	virtual void ResetState() {;};
	/// Synchronize state for a new stream - this *MUST* be called before beginning a new parsing stream
	virtual void SynchronizeStateForNewStream() {;};
	/// Prepare for coding mode; returns true on success
	/// @return true on success
	virtual bool PrepareForCoding(OctaneModeler *modelerp) {return true;};
	/// Are we ready to actually code and decode?
	/// @return true on success
	virtual bool IsReadyToCode() {return true;};
	//---------------------------------------------------------------------------
public:
	//---------------------------------------------------------------------------
	// CODER PUBLIC API - MODEL CHANGE NOTIFICATION
	/// Notify coder that all probabilities are being updated.
	/// We can be informed by a model when the underlying probabilities are changing
	///  this part of the API exists so that we can flexibly and efficiently
	///  handle different kinds of situations where the coder needs to be synchronized
	///  with the model probabilities.  in some cases, a coder may ignore these
	///  messages and simply rebuild its internal datastructure on each coding event
	///  in other cases, it will want to incrementally update as model changes.
	/// Two kinds of notifications are supported, depending on how the model updates
	///  itself during processing, whether it updates one symbol per iteration, or
	///  modifies all symbols at once.
	/// @see OctaneCoder::ReceiveNotification_ModelChange_SingleSymbolWeight
	virtual void ReceiveNotification_ModelChange_AllSymbolWeights(OctaneModeler *modelerp) {;};
	/// notify that a single symbol probability has changed (by default just calls AllSymbolWeights change above)
	/// @note the SingleSymbolWeight() call will NOT be made when all weights change; see ReceiveNotification_ModelChange_AllSymbolWeights instead.
	/// @see OctaneCoder::ReceiveNotification_ModelChange_AllSymbolWeights
	virtual void ReceiveNotification_ModelChange_SingleSymbolWeight(OctaneModeler *modelerp,int symbolnum) {ReceiveNotification_ModelChange_AllSymbolWeights(modelerp);};
	//---------------------------------------------------------------------------
public:
	//---------------------------------------------------------------------------
	/// Align output stream - called after writing an End-of-stream symbol
	/// This throws away any spare bits in the output which are not aligned on a byte boundary.
	/// This is required when we hit and end of stream symbol, to avoid treating leftover bits as meaningful symbols.
	/// @return true on success
	void AlignOutputStreamToByteBoundry(bitwriter &bw) {bw.align_byte();};
	/// Align input stream - called after reading an End-of-stream symbol
	/// This throws away any spare bits in the output which are not aligned on a byte boundary.
	/// This is required when we hit and end of stream symbol, to avoid treating leftover bits as meaningful symbols.
	/// @return true on success
	void AlignInputStreamToByteBoundry(bitreader &br) {br.align_byte();};
	//---------------------------------------------------------------------------
};
//---------------------------------------------------------------------------



//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------

