#ifndef _LIVOX_GEN1_PCLOUD_AMBIENCE_QUALE_IFACE_API_H
#define _LIVOX_GEN1_PCLOUD_AMBIENCE_QUALE_IFACE_API_H

#include <cstdint>
#include <memory>
#include <stdexcept>
#include <string>
#include <string_view>
#include <user/deviceAttachmentSpec.h>
#include <user/intrin.h>
#include <user/intrinThresholdParams.h>

namespace smo {
namespace stim_buff {

enum ParamComparatorOp
{
	OP_CMP_GT,
	OP_CMP_LT,
};

struct ParamComparator
{
	ParamComparatorOp op;
	uint32_t value;

	bool operator()(float passbandMetricVal) const
	{
		switch (op)
		{
			case OP_CMP_GT:
				return passbandMetricVal > static_cast<float>(value);
			case OP_CMP_LT:
				return passbandMetricVal < static_cast<float>(value);
		}

		throw std::runtime_error("Unsupported ParamComparatorOp");
	}
};

/* pcloudLightAmbience requires exactly one `passband-count-gt-val` on its
 * qualeIfaceApi params; `passband-count-lt-val` is a hard error. Feeds a
 * negtrin(...) segment (scene is "unbearably much, get away").
 */
inline ParamComparator parsePcloudLightAmbienceGtComparator(
	const std::shared_ptr<device::DeviceAttachmentSpec>& deviceAttachmentSpec)
{
	const auto& params = deviceAttachmentSpec->qualeIfaceApiParams;

	if (device::DeviceAttachmentSpec::paramsContain(
		params, "passband-count-lt-val"))
	{
		throw std::runtime_error(
			"pcloudLightAmbience qualeIfaceApi does not accept "
			"'passband-count-lt-val'; use pcloudDarkAmbience for lt-val "
			"pipelines.");
	}

	constexpr int kParamNotSpecified = -1;
	const int gtVal = device::DeviceAttachmentSpec::parseOptionalParamAsInt(
		params, "passband-count-gt-val", kParamNotSpecified);

	if (gtVal == kParamNotSpecified)
	{
		throw std::runtime_error(
			"pcloudLightAmbience qualeIfaceApi requires "
			"'passband-count-gt-val' on its params.");
	}

	return ParamComparator{
		.op = OP_CMP_GT,
		.value = static_cast<uint32_t>(gtVal),
	};
}

/* pcloudDarkAmbience requires exactly one `passband-count-lt-val` on its
 * qualeIfaceApi params; `passband-count-gt-val` is a hard error. Feeds a
 * postrin(...) segment (scene is "too good, stay here").
 */
inline ParamComparator parsePcloudDarkAmbienceLtComparator(
	const std::shared_ptr<device::DeviceAttachmentSpec>& deviceAttachmentSpec)
{
	const auto& params = deviceAttachmentSpec->qualeIfaceApiParams;

	if (device::DeviceAttachmentSpec::paramsContain(
		params, "passband-count-gt-val"))
	{
		throw std::runtime_error(
			"pcloudDarkAmbience qualeIfaceApi does not accept "
			"'passband-count-gt-val'; use pcloudLightAmbience for gt-val "
			"pipelines.");
	}

	constexpr int kParamNotSpecified = -1;
	const int ltVal = device::DeviceAttachmentSpec::parseOptionalParamAsInt(
		params, "passband-count-lt-val", kParamNotSpecified);

	if (ltVal == kParamNotSpecified)
	{
		throw std::runtime_error(
			"pcloudDarkAmbience qualeIfaceApi requires "
			"'passband-count-lt-val' on its params.");
	}

	return ParamComparator{
		.op = OP_CMP_LT,
		.value = static_cast<uint32_t>(ltVal),
	};
}

/* Shared parser used by both pcloudLightAmbience and pcloudDarkAmbience
 * stimbuffs to decode a postrin(...) / negtrin(...) segment's threshold
 * params into an IntrinConfig. Kept with the qualeIfaceApi helpers because
 * it's ambience-specific (nDgramsPerFrame is the percentage base).
 */
inline intrin::IntrinConfig parseAmbienceIntrinConfigFromParams(
	std::string_view intrinKind,
	const std::vector<std::pair<std::string, std::string>>& params,
	size_t nDgramsPerFrame)
{
	intrin::validateIntrinSegmentParams(intrinKind, params);

	const auto threshold = intrin::parseOptionalThresholdParam(
		params,
		intrin::kIntrinInterestPcNames,
		intrin::kIntrinInterestThrNames,
		/*defaultValue=*/0,
		/*defaultUnit=*/intrin::ThresholdUnit::Absolute);

	return intrin::IntrinConfig{
		.percentage =
			threshold.unit == intrin::ThresholdUnit::Percentage
				? static_cast<uint32_t>(threshold.value)
				: 0U,
		.threshold = intrin::resolveThresholdValue(
			threshold, nDgramsPerFrame),
	};
}

} // namespace stim_buff
} // namespace smo

#endif // _LIVOX_GEN1_PCLOUD_AMBIENCE_QUALE_IFACE_API_H
