/*
 * Author: Radovan Cerveny
 */

#include "../MeasurementFrame.hpp"

namespace measurements {

void CounterDataFrame::init ( unsigned frameIdx, measurements::stealth_vector < MeasurementFrame > & frames ) {
	MeasurementFrame & currentFrame = frames[frameIdx];
	MeasurementFrame & parentFrame	= frames[currentFrame.parentIdx];

	if ( parentFrame.type != measurements::Type::ROOT )
		currentFrame.counter.counters = parentFrame.counter.counters;
}

void CounterDataFrame::update ( unsigned, measurements::stealth_vector < MeasurementFrame > & ) {
	// noop, updates take place during hint resolution
}

void CounterDataFrame::hint ( unsigned frameIdx, measurements::stealth_vector < MeasurementFrame > & frames, CounterHint hint ) {
	if ( frames[frameIdx].type == measurements::Type::ROOT ) return;

	CounterHint::value_type delta = 0;

	switch ( hint.type ) {
	case CounterHint::Type::ADD:
		delta = hint.value;
		break;

	case CounterHint::Type::SUB:
		delta = -hint.value;
		break;
	}

	frames[frameIdx].counter.inFrameCounters[hint.name] += delta;

	unsigned curIdx = frameIdx;

	for ( ; ; ) {
		MeasurementFrame & currentFrame = frames[curIdx];

		if ( currentFrame.type == measurements::Type::ROOT ) break;

		currentFrame.counter.counters[hint.name] += delta;

		curIdx = currentFrame.parentIdx;
	}
}

CounterDataFrame CounterDataFrame::aggregate ( const std::vector < MeasurementFrame > & framesToAggregate ) {
	 // FIXME dummmy aggregation
	return framesToAggregate[0].counter;
}

std::ostream & operator <<( std::ostream & os, const CounterDataFrame & cdf ) {

	os << "cnts: (";

	for ( auto it = cdf.counters.begin ( ); it != cdf.counters.end ( ); ++it ) {
		if ( it != cdf.counters.begin ( ) ) os << ", ";

		os << it->first << " : " << it->second;
	}

	os << "), if_cnts: (";

	for ( auto it = cdf.inFrameCounters.begin ( ); it != cdf.inFrameCounters.end ( ); ++it ) {
		if ( it != cdf.inFrameCounters.begin ( ) ) os << ", ";

		os << it->first << " : " << it->second;
	}

	os << ")";

	return os;
}

}
