//..............................................................................
//
// ModBus Protocol Analyzer log record declarations and representer
//

import "log.jnc"
import "io_ModBus.jnc"

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

enum ModBusRtuLogRecordCode
{
	// need to avoid conflicts with SerialLog and SerialMonLog
	MasterPacket    = 0x200 | log.RecordCodeFlags.Foldable,
	SlavePacket     = 0x201 | log.RecordCodeFlags.Foldable,
	InvalidFunction = 0x204,
}

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

bool representModBusRtuLog (
	log.RepresenterTarget* target,
	uint_t recordCode,
	void const* p,
	size_t size,
	uint_t foldFlags
	)
{
	io.ModBusRole role;

	switch (recordCode)
	{
	case ModBusRtuLogRecordCode.MasterPacket:
		role = io.ModBusRole.Master;
		break;

	case ModBusRtuLogRecordCode.SlavePacket:
		role = io.ModBusRole.Slave;
		break;

	case ModBusRtuLogRecordCode.InvalidFunction:
		uint8_t code = *(uint8_t const*) p;
		target.m_lineAttr.m_backColor = gui.StdColor.PastelYellow;
		target.m_lineAttr.m_iconIdx = log.StdLogIcon.Warning;
		target.addHyperText ($"Invalid or unsupported function: \e[31m0x%(1; 02X)/%1\e[m" (code));
		return true;

	default:
		return false;
	}

	io.ModBusRtuAduHdr const* aduHdr = (io.ModBusRtuAduHdr const*) p;
	io.ModBusPduHdr const* pduHdr = (io.ModBusPduHdr const*) (aduHdr + 1);

	target.m_lineAttr.m_backColor = gui.StdColor.PastelGray;
	target.m_lineAttr.m_iconIdx = role == io.ModBusRole.Master ?
		log.StdLogIcon.TxPacket :
		log.StdLogIcon.RxPacket;

	target.addHyperText (
		$"Address:   \e^!-%1,%2\e[34m0x%(3; 02X)/%3\e[m" (
		offsetof (aduHdr.m_deviceAddress),
		sizeof (aduHdr.m_deviceAddress),
		aduHdr.m_deviceAddress
		));

	size_t checksumOffset = size - sizeof (uint16_t);
	uint16_t actualChecksum = *(uint16_t const*) (p + checksumOffset);
	uint16_t expectedChecksum = crc16_ansi (p, checksumOffset, 0xffff);

	if (actualChecksum == expectedChecksum)
	{
		target.addHyperText (
			$"Checksum:  \e^!-%1,%2\e[34m0x%(3; 04X)/%3\e[m [\e[32mOK\e[m]" (
			checksumOffset,
			sizeof (uint16_t),
			actualChecksum
			));
	}
	else
	{
		target.addHyperText (
			$"Checksum:  \e^!-%1,%2\e[34m0x%(3; 04X)/%3\e[m [\e[31mERROR\e[m] \e[90m(expected: 0x%(4; 04X)/%4)\e[m" (
			checksumOffset,
			sizeof (uint16_t),
			actualChecksum,
			expectedChecksum
			));
	}

	representModBusPdu (
		target,
		role,
		pduHdr,
		size - sizeof (io.ModBusRtuAduHdr),
		sizeof (io.ModBusRtuAduHdr),
		foldFlags
		);

	return true;
}

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