/**
 * Copyright (c) 2017-2026 Governikus GmbH & Co. KG, Germany
 */


#include "IfdTransmit.h"

#include <QJsonArray>
#include <QLoggingCategory>


Q_DECLARE_LOGGING_CATEGORY(ifd)


using namespace governikus;


namespace
{
VALUE_NAME(COMMAND_APDUS, "CommandAPDUs")
VALUE_NAME(INPUT_APDU, "InputAPDU")
VALUE_NAME(DISPLAY_TEXT, "DisplayText")
VALUE_NAME(ACCEPTABLE_STATUS_CODES, "AcceptableStatusCodes")
} // namespace


void IfdTransmit::parseInputApdu(const QJsonObject& pMessageObject)
{
	const bool v0Supported = IfdVersion(IfdVersion::Version::v0).isSupported();

	bool inputApduFound = false;
	if (v0Supported && pMessageObject.contains(COMMAND_APDUS()))
	{
		inputApduFound = true;
		const auto& value = pMessageObject.value(COMMAND_APDUS());
		if (value.isArray())
		{
			const auto& entry = value.toArray().at(0);
			if (entry.isObject())
			{
				const QJsonObject& commandApdu = entry.toObject();
				const QString& inputApdu = getStringValue(commandApdu, INPUT_APDU());
				mInputApdu = QByteArray::fromHex(inputApdu.toUtf8());
			}
			else
			{
				invalidType(COMMAND_APDUS(), QLatin1String("object array"));
			}

			if (value.toArray().size() > 1)
			{
				qCDebug(ifd) << "Only using the first CommandAPDU. Command chaining is not supported yet";
			}
		}
		else
		{
			invalidType(COMMAND_APDUS(), QLatin1String("array"));
		}
	}

	if (!v0Supported || pMessageObject.contains(INPUT_APDU()))
	{
		inputApduFound = true;
		const QString& inputApdu = getStringValue(pMessageObject, INPUT_APDU());
		mInputApdu = QByteArray::fromHex(inputApdu.toUtf8());
	}

	if (!inputApduFound)
	{
		missingValue(COMMAND_APDUS());
		missingValue(INPUT_APDU());
	}
}


IfdTransmit::IfdTransmit(const QString& pSlotHandle, const QByteArray& pInputApdu, const QString& pDisplayText)
	: IfdSlotHandle<IfdMessage>(IfdMessageType::IFDTransmit, pSlotHandle)
	, mInputApdu(pInputApdu)
	, mDisplayText(pDisplayText)
{
}


IfdTransmit::IfdTransmit(const QJsonObject& pMessageObject)
	: IfdSlotHandle<IfdMessage>(pMessageObject)
	, mInputApdu()
	, mDisplayText()
{
	parseInputApdu(pMessageObject);

	if (pMessageObject.contains(DISPLAY_TEXT()))
	{
		mDisplayText = getStringValue(pMessageObject, DISPLAY_TEXT());
	}

	ensureType(IfdMessageType::IFDTransmit);
}


const QByteArray& IfdTransmit::getInputApdu() const
{
	return mInputApdu;
}


const QString& IfdTransmit::getDisplayText() const
{
	return mDisplayText;
}


QByteArray IfdTransmit::toByteArray(IfdVersion::Version pIfdVersion, const QString& pContextHandle) const
{
	QJsonObject result = createMessageBody(pContextHandle);

	if (pIfdVersion >= IfdVersion::Version::v2)
	{
		result[INPUT_APDU()] = QString::fromLatin1(mInputApdu.toHex());
		if (!mDisplayText.isNull())
		{
			result[DISPLAY_TEXT()] = mDisplayText;
		}
	}
	else
	{
		QJsonArray commandApdus;
		QJsonObject commandApdu;
		commandApdu[INPUT_APDU()] = QString::fromLatin1(mInputApdu.toHex());
		commandApdu[ACCEPTABLE_STATUS_CODES()] = QJsonValue();
		commandApdus += commandApdu;
		result[COMMAND_APDUS()] = commandApdus;
	}

	return IfdMessage::toByteArray(result);
}
