#include "history.hh"
#include <iostream>

History::History(){}
History::~History(){}
History::History(const std::string& text)
{
	buildFromText(text);
}

History::Iterator History::begin() const
{
	return theOperations.begin();
}

History::Iterator History::end() const
{
	return theOperations.end();
}

void History::buildFromText(const std::string& text)
{
	theOperations.clear(); //remove previous content
	std::string::size_type currentPosition = 0;
	std::string::size_type length = text.length();
	while(currentPosition+1<=length) //we need to read at least 2 characters
	{
		char dataElement = '0'; //empty element by default (e.g. for commit and abort)
		if(text.at(currentPosition)==',' || text.at(currentPosition)==';')
			++currentPosition; //allow to use , and ; as seperators
		char operation = text.at(currentPosition);
		++currentPosition;
		unsigned int transactionID = atoi(&text.at(currentPosition));
		Operation::OperationKind kind = Operation::INVALID;
		if(operation=='a' || operation=='A')
			kind = Operation::ABORT;
		else if(operation=='c' || operation=='C')
			kind = Operation::COMMIT;
		else
		{
			if(operation=='r' || operation=='R')
				kind = Operation::READ;
			else if(operation=='w' || operation=='W')
				kind = Operation::WRITE;

			if(kind!=Operation::INVALID)
			{
				//got a read or a write operation, extract data element
				if(currentPosition+2>length)
				{
					std::cerr<<"Unexpected end of input, aborting"<<std::endl;
					break; //not enougth input left
				}
				++currentPosition;
				if(text.at(currentPosition)!='[' && text.at(currentPosition)!='(')
				{
					std::cerr<<"Unexpected seperator, expecting [ or (, got "<<text.at(currentPosition)
						<<std::endl;
					break; //unexpected seperator
				}
				++currentPosition;
				dataElement = text.at(currentPosition);
				++currentPosition;
				if(text.at(currentPosition)!=']' && text.at(currentPosition)!=')')
				{
					std::cerr<<"Unexpected seperator, expecting ] or ), got "<<text.at(currentPosition)
						<<std::endl;
					break; //unexpected seperator
				}
			}
		}
		theOperations.push_back(Operation(kind, dataElement, transactionID)); //add element
		++currentPosition;
	}
}

std::ostream& operator<<(std::ostream& ostream, const History& H)
{
	for(History::Iterator cit = H.begin(); cit != H.end(); ++cit)
	{
		ostream<<cit->getText();
	}
	return ostream;
}

