//..............................................................................
//
// Some standard stats collected via selection processors
//

import "log_RangeProcessor.jnc"
import "ui_ThroughputInfoSet.jnc"
import "formatInteger.jnc"

namespace log {

//! \addtogroup common-log
//! @{

//..............................................................................

class ThroughputCalcRangeProcessor: RangeProcessor {
protected:
	ui.ThroughputInfoSet* m_infoSet;
	uint64_t m_startTimestamp;
	uint64_t m_txTotalSize;
	uint64_t m_rxTotalSize;
	uint64_t m_totalSize;

public:
	static ThroughputCalcRangeProcessor* factory(ui.ThroughputInfoSet* infoSet) {
		return new ThroughputCalcRangeProcessor(infoSet);
	}

protected:
	construct(ui.ThroughputInfoSet* infoSet) {
		m_infoSet = infoSet;
	}

	override processText(
		uint64_t partCode,
		string_t text
	);

	override processBin(
		uint64_t partCode,
		void const* p,
		size_t size
	);

	override processDualBin(
		uint64_t partCode,
		void const* p1,
		void const* p2,
		size_t size
	);

	override processEndOfRange();
}

// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

void ThroughputCalcRangeProcessor.processText(
	uint64_t partCode,
	string_t text
) {
	if (!m_startTimestamp)
		m_startTimestamp = m_timestamp;
}

void ThroughputCalcRangeProcessor.processBin(
	uint64_t partCode,
	void const* p,
	size_t size
) {
	if (!m_startTimestamp)
		m_startTimestamp = m_timestamp;

	switch (partCode) {
	case StdRecordCode.Tx:
		m_txTotalSize += size;
		break;

	case StdRecordCode.Rx:
		m_rxTotalSize += size;
		break;
	}

	m_totalSize += size;
}

void ThroughputCalcRangeProcessor.processDualBin(
	uint64_t partCode,
	void const* p1,
	void const* p2,
	size_t size
) {
	if (!m_startTimestamp)
		m_startTimestamp = m_timestamp;

	switch (partCode) {
	case StdRecordCode.TxRx:
		m_txTotalSize += size;
		m_rxTotalSize += size;
		break;
	}

	m_totalSize += size * 2;
}

void ThroughputCalcRangeProcessor.processEndOfRange() {
	uint64_t timeSpan = m_timestamp - m_startTimestamp;

	if (m_infoSet.m_timeSpanInfo)
		m_infoSet.m_timeSpanInfo.m_value = $"$(sys.formatTimestamp (timeSpan, 0, "%h:%m:%s.%l"))";

	if (m_infoSet.m_txTotalSizeInfo)
		m_infoSet.m_txTotalSizeInfo.m_value = formatIntegerWithThousandSep(m_txTotalSize);

	if (m_infoSet.m_rxTotalSizeInfo)
		m_infoSet.m_rxTotalSizeInfo.m_value = formatIntegerWithThousandSep(m_rxTotalSize);

	if (m_infoSet.m_totalSizeInfo)
		m_infoSet.m_totalSizeInfo.m_value = formatIntegerWithThousandSep(m_totalSize);

	if (timeSpan) {
		if (m_infoSet.m_txThroughputInfo)
			m_infoSet.m_txThroughputInfo.m_value = formatIntegerWithThousandSep(m_txTotalSize * 10000000 / timeSpan);

		if (m_infoSet.m_rxThroughputInfo)
			m_infoSet.m_rxThroughputInfo.m_value = formatIntegerWithThousandSep(m_rxTotalSize * 10000000 / timeSpan);

		if (m_infoSet.m_totalThroughputInfo)
			m_infoSet.m_totalThroughputInfo.m_value = formatIntegerWithThousandSep(m_totalSize * 10000000 / timeSpan);
	} else {
		string_t text = "insufficient time span";

		if (m_infoSet.m_txThroughputInfo)
			m_infoSet.m_txThroughputInfo.m_disabledValue = text;

		if (m_infoSet.m_rxThroughputInfo)
			m_infoSet.m_rxThroughputInfo.m_disabledValue = text;

		if (m_infoSet.m_totalThroughputInfo)
			m_infoSet.m_totalThroughputInfo.m_disabledValue = text;
	}
}

//..............................................................................

//! @}

} // namespace log
