//..............................................................................
//
// Modbus stream parser base class
//

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

enum ModbusParserMode {
	None,
	Master,
	Slave,
	Alternate,
}

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

class ModbusParserBase {
protected:
	ModbusInfoSet* m_infoSet;
	io.ModbusRole m_modbusRole;
	uint64_t m_lastTimestamp;

public:
	io.ModbusProtocol readonly m_protocol;
	ModbusParserMode autoget property m_mode;
	uint64_t m_alternateTimeout; // in 100-nsec intervals

public:
	construct(
		io.ModbusProtocol readonly protocol,
		ModbusInfoSet* infoSet
	) {
		m_protocol = protocol;
		m_infoSet = infoSet;
	}

	abstract void parse(
		log.Writer* writer,
		uint64_t timestamp,
		uint64_t originalRecordCode,
		void const* p,
		size_t size
	);

	virtual void reset() {
		if (m_mode == ModbusParserMode.Alternate)
			m_modbusRole = io.ModbusRole.Master;
	}

protected:
	void updateLastTimestamp(uint64_t timestamp);
}

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

void ModbusParserBase.m_mode.set(ModbusParserMode mode) {
	if (mode == m_value)
		return;

	m_value = mode;
	m_modbusRole = mode == ModbusParserMode.Slave ?
		io.ModbusRole.Slave :
		io.ModbusRole.Master;

	reset();
}

void ModbusParserBase.updateLastTimestamp(uint64_t timestamp) {
	if (m_mode == ModbusParserMode.Alternate &&
		timestamp - m_lastTimestamp > m_alternateTimeout
	)
		reset();

	m_lastTimestamp = timestamp;
}

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