//..............................................................................
//
// SPI tap log packet declarations and representer
//

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

enum SpiTapLogRecordCode
{
	TapOpened     = 0 | log.RecordCodeFlags.Foldable,
	TapOpenError  = 2,
	TapClosed,
	FrequencyChanged,
	ModeChanged,
	DataBitsChanged,
	EndiannessChanged,
	TxRxOutOfSync,
}

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

struct SpiTapOpenParams
{
	uint_t m_frequency;
	uint_t m_mode;
	uint_t m_dataBits;
	uint_t m_endianness;

	// followed by device name
}

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

char const* getTableString (
	uint_t value,
	char const* const* table
	)
{
	return value < dynamic countof (table) ? table [value] : "\e[31mundefined\e[m";
}

bool representSpiTapLog (
	log.RepresenterTarget* target,
	uint_t recordCode,
	void const* p,
	size_t size,
	uint_t foldFlags
	)
{
	static char const* endiannessStringTable [] =
	{
		"Little-endian (LSBit first)",
		"Big-endian (MSBit first)",
	}
	switch (recordCode)
	{
	case SpiTapLogRecordCode.TapOpened:
		SpiTapOpenParams const* params = (SpiTapOpenParams const*) p;
		char const* name = (char const*) (params + 1);

		target.m_lineAttr.m_iconIdx = log.StdLogIcon.Connect;
		target.m_lineAttr.m_backColor = log.StdLogColor.Connect;

		char const* string;

		if (!(foldFlags & 1))
		{
			string =
				$"[\e^+1\e[34m+\e[m] Opened tap \e[34m$name\e[m "
				$"\e[34m$(params.m_frequency)\e[m Hz "
				$"SPI mode $(params.m_mode)";
		}
		else
		{
			char const* endiannessString = getTableString (params.m_endianness, endiannessStringTable);

			string =
				$"[\e^-1\e[34m-\e[m] Opened tap \e[34m$name\n"
				$"    \e[90mClock:      \e[34m$(params.m_frequency)\e[m Hz\n"
				$"    \e[90mSPI mode:   \e[34m$(params.m_mode)\n"
				$"    \e[90mData bits:  $(params.m_dataBits)\n"
				$"    \e[90mEndianness: \e[34m$endiannessString";
		}

		target.addHyperText (string);
		break;

	case SpiTapLogRecordCode.TapClosed:
		char const* name = (char const*) p;
		target.m_lineAttr.m_iconIdx = log.StdLogIcon.Disconnect;
		target.m_lineAttr.m_backColor = log.StdLogColor.Disconnect;
		target.addHyperText ($"Port \e[34m$name\e[m closed");
		break;

	case SpiTapLogRecordCode.TapOpenError:
		std.Error const* error = (std.Error const*) p;
		target.m_lineAttr.m_iconIdx = log.StdLogIcon.Error;
		target.m_lineAttr.m_backColor = log.StdLogColor.Error;
		target.addHyperText ($"Cannot open port: $(error.m_description)");
		break;

	case SpiTapLogRecordCode.FrequencyChanged:
		uint_t frequency = *(uint_t const*) p;

		target.m_lineAttr.m_iconIdx = log.StdLogIcon.Info;
		target.m_lineAttr.m_backColor = log.StdLogColor.Info;
		target.addHyperText ($"Set clock frequency: \e[34m$frequency\e[m Hz");
		break;

	case SpiTapLogRecordCode.ModeChanged:
		uint_t mode = *(uint_t const*) p;
		target.m_lineAttr.m_iconIdx = log.StdLogIcon.Info;
		target.m_lineAttr.m_backColor = log.StdLogColor.Info;
		target.addHyperText ($"Set SPI mode: \e[34m$mode");
		break;

	case SpiTapLogRecordCode.DataBitsChanged:
		uint_t dataBits = *(uint_t const*) p;

		target.m_lineAttr.m_iconIdx = log.StdLogIcon.Info;
		target.m_lineAttr.m_backColor = log.StdLogColor.Info;
		target.addHyperText ($"Set data bits: \e[34m$dataBits\e[m bits");
		break;

	case SpiTapLogRecordCode.EndiannessChanged:
		bool isMsbFirst = *(bool const*) p;
		char const* endiannessString = getTableString (isMsbFirst, endiannessStringTable);

		target.m_lineAttr.m_iconIdx = log.StdLogIcon.Info;
		target.m_lineAttr.m_backColor = log.StdLogColor.Info;
		target.addHyperText ($"Set endianness: $endiannessString");
		break;

	case SpiTapLogRecordCode.TxRxOutOfSync:
		target.m_lineAttr.m_iconIdx = log.StdLogIcon.Info;
		target.m_lineAttr.m_backColor = log.StdLogColor.Info;
		target.addHyperText ($"SPI MOSI and MISO out-of-sync");
		break;

	default:
		return false;
	}

	return true;
}

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