/// @file samplecompressor.cpp
/// Sample compressor
///
/// @remarks
/// This is a silly sample compressor which does nothing useful.
///
/// @note if you are interested in making a statistical style compressor,
/// then you should see the samplestatcompressor.
///
/// @author mouser
/// @date   2003.08.12
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
// application includes
#include "samplecompressor.hpp"
// system includes
#include <iomanip>
using namespace std;
//---------------------------------------------------------------------------


//---------------------------------------------------------------------------
// Create a global instance in order to register it automatically with the global manager
SampleCompressor GloballyInstantiated_SampleCompressor(true);
//---------------------------------------------------------------------------


//---------------------------------------------------------------------------
// Constructor
SampleCompressor::SampleCompressor(bool registerme)
	:OctaneCompressor(registerme)
{
	// REGISTER WITH COMPRESSOR MANAGER
	//  this use a trick to make sure the global manager is ready for registration
 	//  and at the same time automatically register this instance with the global manager
 	// note that the insurer is just temporary, and deletes when we exit the procedure
 	if (registerme)
		CompressorManager_SingletonInsurer managerinsurance(this);
	
	// set default parameters for the compressor
	SetDefaultParameters();
}
//---------------------------------------------------------------------------



//---------------------------------------------------------------------------
// OCTANE PUBLIC API - AUXILIARY FUNCTIONS - these are supported by all derived classes
void SampleCompressor::ShowDebuggingInfo()
{
	// OPTIONAL: Here we can show any information that could be useful during testing.
	// If this function is not defined, nothing is shown, but we implement it here for fun.
	cout << "This is the sample compressor, there is no useful debugging information to display.  ";
	cout << "But for fun, i'll tell you that this compressor lives at the following memory address: "<< (void *)this<<endl;
}

unsigned int SampleCompressor::GetMemoryUsed()
{
	// here we return an estimate of the memory used by this compressor
	return sizeof(this);
}

unsigned int SampleCompressor::GetDiskspaceUsed(bool fortempdecompressiononly)
{
	// Here we return an estimate of the disk space used to save our state
	//  in this case, we have a single char variable which makes up our state
	// The flag fortempdecompressiononly will be set if the state is being saved for decompression *only*
	//  see SaveState() for how this is used, and adjust disk space appropriately if you save different information.
	return sizeof(Parameter_xorbyte);
}

std::string SampleCompressor::GetParametersInformation()
{
	// Show user available variables and their current values
	// ATTN: this has not been converted from cout to string yet, so just send output to cout and return an empty string
	cout << setiosflags(ios::left) << setw(17) << "xorbyte" << setiosflags(ios::left) << " " << setw(10) << (int)Parameter_xorbyte << " " << "byte (0-255) to xor text with during processing" << endl;
	return "";
}

void SampleCompressor::SetDefaultParameters()
{
	// Set parameters to their defaults
	Parameter_xorbyte=65;
}

bool SampleCompressor::SetParameter(const std::string &parametername,const std::string &parametervalue)
{
	// Generic function for user-interactive modification of parameters
	// Return true if we know this variable and use it
	bool bretv=false;
	
	// we have 1 variable we use, called xorbyte
	if (parametername=="xorbyte")
		bretv=ParseParameter(parametervalue,Parameter_xorbyte);
		
	// return success
	return bretv;
}
//---------------------------------------------------------------------------


//---------------------------------------------------------------------------
// COMPRESSOR PUBLIC API - PREPARATION FOR COMPRESSING/DECOMPRESSING
bool SampleCompressor::IsReadyToCompress()
{
	// Are we ready to compress?
	// This sample compressor is always ready (needs no training)
	return true;
}
//---------------------------------------------------------------------------



//---------------------------------------------------------------------------
// COMPRESSOR DERIVED COMPRESSION/DECOMPRESSING - implement these in derived classes
bool SampleCompressor::DoProtectedCompress(bitreader &from, bitwriter &to)
{
	// Here is the main compression routine
	// Our sample compressor doesn't actually compress, instead it just xors 

	// loop through input and 'compress' (xor) it
	unsigned char c;
	while (!from.empty())
		{
		// grab a character from input
		c=from.get_byte();
		// xor it with our parameter
		c= c ^ Parameter_xorbyte;
		// send it to output
		to.put_byte(c);
		}

	// return success
	return true;
}


bool SampleCompressor::DoProtectedDecompress(bitreader &from, bitwriter &to)
{
	// Here is the main decompression routine
	// Our sample compressor doesn't actually decompress, instead it just xors 

	// loop through input and 'compress' (xor) it
	unsigned char c;
	while (!from.empty())
		{
		// grab a character from input
		c=from.get_byte();
		// xor it with our parameter
		c= Parameter_xorbyte ^ c;
		// send it to output
		to.put_byte(c);
		}

	// return success
	return true;
}
//---------------------------------------------------------------------------



//---------------------------------------------------------------------------
// OCTANE PROTECTED DERIVED STATE LOADING AND SAVING
bool SampleCompressor::DoProtectedCreateSymbolsAndModelsUsingStream(bitreader &from)
{
	// OPTIONAL: this is called to 'train' a compressor, to let a compressor gather statistics from an input stream.
	// Our sample compressor does not need to implement this, but we include it here just for fun so you see what it looks like.
	// return false only on an error.
	
	// let's read the training input stream, just to show you how its done.
	unsigned char c;
	while (!from.empty())
		{
		// grab a character, but we dont do anything with it.
		c=from.get_byte();
		}

	// return success
	return true;
}

bool SampleCompressor::DoProtectedSaveState(bitwriter &to,bool fortempdecompressiononly)
{
	// OPTIONAL: save any compressor internal state (like variables or learned statistics).
	// Many compressors have no interenal state to save, but this sample compressor has a variable
	//  which should be saved.
	// The flag fortempdecompressiononly will be set if the state is being saved for decompression *only*
	//  so that if there is some information is only needed for compression, we dont have to save it if we dont need it.

	// just tell the bitwriter to save the variables
	to.put(Parameter_xorbyte);

	// return true on success
	return true;
}

bool SampleCompressor::DoProtectedLoadState(bitreader &from)
{
	// OPTIONAL: load any compressor internal state (like variables or learned statistics).
	// Many compressors have no interenal state to save, but this sample compressor has a variable
	//  which should be saved.

	// just tell the bitwriter to save the variables
	from.get(Parameter_xorbyte);

	// return true on success
	return true;
}
//---------------------------------------------------------------------------
