#include <planarYuvFormatPolicy.h>
#include <gtest/gtest.h>
#include <libcamera/formats.h>
#include <support/exceptionAssertions.h>
#include <vector>

namespace lcamera_dev {
namespace {

using libcamera::formats::MJPEG;
using libcamera::formats::NV12;
using libcamera::formats::YUYV;
using libcamera::formats::YUV420;

TEST(PlanarYuvFormatPolicyTest, FullyPlanarRequiredPicksYuv420OverNv12)
{
	const std::vector<libcamera::PixelFormat> candidates = {YUV420, NV12};

	const std::optional<libcamera::PixelFormat> selected =
		selectYuvCaptureFormat(candidates, false);

	EXPECT_TRUE(selected.has_value());
	EXPECT_EQ(*selected, YUV420);
	EXPECT_TRUE(isFullyPlanarYuv(*selected));
}

TEST(PlanarYuvFormatPolicyTest, FullyPlanarRequiredThrowsWhenOnlyNonPlanar)
{
	const std::vector<libcamera::PixelFormat> candidates = {NV12, YUYV};

	try {
		selectYuvCaptureFormat(candidates, false);
		FAIL() << "Expected runtime_error";
	}
	catch (const std::runtime_error& exception)
	{
		sscl::tests::expectExceptionMessageContains(
			exception,
			"planar");
	}
}

TEST(PlanarYuvFormatPolicyTest, FullyPlanarOptionalPicksNv12)
{
	const std::vector<libcamera::PixelFormat> candidates = {NV12};

	const std::optional<libcamera::PixelFormat> selected =
		selectYuvCaptureFormat(candidates, true);

	EXPECT_TRUE(selected.has_value());
	EXPECT_EQ(*selected, NV12);
	EXPECT_FALSE(isFullyPlanarYuv(*selected));
	EXPECT_EQ(yuvCapturePlaneCount(*selected), 2u);
}

TEST(PlanarYuvFormatPolicyTest, EmptyCandidateListThrows)
{
	const std::vector<libcamera::PixelFormat> candidates;

	EXPECT_THROW(
		selectYuvCaptureFormat(candidates, false),
		std::runtime_error);
}

TEST(PlanarYuvFormatPolicyTest, IsFullyPlanarYuvRecognizesYuv420)
{
	EXPECT_TRUE(isFullyPlanarYuv(YUV420));
	EXPECT_FALSE(isFullyPlanarYuv(NV12));
}

TEST(PlanarYuvFormatPolicyTest, FullyPlanarOptionalPicksYuyvOverMjpeg)
{
	const std::vector<libcamera::PixelFormat> candidates = {MJPEG, YUYV};

	const std::optional<libcamera::PixelFormat> selected =
		selectYuvCaptureFormat(candidates, true);

	EXPECT_TRUE(selected.has_value());
	EXPECT_EQ(*selected, YUYV);
	EXPECT_FALSE(isFullyPlanarYuv(*selected));
	EXPECT_EQ(yuvCapturePlaneCount(*selected), 1u);
}

} // namespace
} // namespace lcamera_dev
