/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * Copyright (C) 2020, Google Inc.
 * Copyright (C) 2021, Collabora Ltd.
 *
 * main.cpp - lc-compliance - The libcamera compliance tool
 */

#include <iomanip>
#include <iostream>
#include <string.h>

#include <gtest/gtest.h>

#include <libcamera/libcamera.h>

#include "environment.h"
#include "../cam/options.h"

using namespace libcamera;

enum {
	OptCamera = 'c',
	OptList = 'l',
	OptFilter = 'f',
	OptHelp = 'h',
};

/*
 * Make asserts act like exceptions, otherwise they only fail (or skip) the
 * current function. From gtest documentation:
 * https://google.github.io/googletest/advanced.html#asserting-on-subroutines-with-an-exception
 */
class ThrowListener : public testing::EmptyTestEventListener
{
	void OnTestPartResult(const testing::TestPartResult &result) override
	{
		if (result.type() == testing::TestPartResult::kFatalFailure ||
		    result.type() == testing::TestPartResult::kSkip)
			throw testing::AssertionException(result);
	}
};

static void listCameras(CameraManager *cm)
{
	for (const std::shared_ptr<Camera> &cam : cm->cameras())
		std::cout << "- " << cam.get()->id() << std::endl;
}

static int initCamera(CameraManager *cm, OptionsParser::Options options)
{
	std::shared_ptr<Camera> camera;

	int ret = cm->start();
	if (ret) {
		std::cout << "Failed to start camera manager: "
			  << strerror(-ret) << std::endl;
		return ret;
	}

	if (!options.isSet(OptCamera)) {
		std::cout << "No camera specified, available cameras:" << std::endl;
		listCameras(cm);
		return -ENODEV;
	}

	const std::string &cameraId = options[OptCamera];
	camera = cm->get(cameraId);
	if (!camera) {
		std::cout << "Camera " << cameraId << " not found, available cameras:" << std::endl;
		listCameras(cm);
		return -ENODEV;
	}

	Environment::get()->setup(cm, cameraId);

	std::cout << "Using camera " << cameraId << std::endl;

	return 0;
}

static int initGtestParameters(char *arg0, OptionsParser::Options options)
{
	const std::map<std::string, std::string> gtestFlags = { { "list", "--gtest_list_tests" },
								{ "filter", "--gtest_filter" } };

	int argc = 0;
	std::string filterParam;

	/*
	 * +2 to have space for both the 0th argument that is needed but not
	 * used and the null at the end.
	 */
	char **argv = new char *[(gtestFlags.size() + 2)];
	if (!argv)
		return -ENOMEM;

	argv[0] = arg0;
	argc++;

	if (options.isSet(OptList)) {
		argv[argc] = const_cast<char *>(gtestFlags.at("list").c_str());
		argc++;
	}

	if (options.isSet(OptFilter)) {
		/*
		 * The filter flag needs to be passed as a single parameter, in
		 * the format --gtest_filter=filterStr
		 */
		filterParam = gtestFlags.at("filter") + "=" +
			      static_cast<const std::string &>(options[OptFilter]);

		argv[argc] = const_cast<char *>(filterParam.c_str());
		argc++;
	}

	argv[argc] = nullptr;

	::testing::InitGoogleTest(&argc, argv);

	delete[] argv;

	return 0;
}

static int initGtest(char *arg0, OptionsParser::Options options)
{
	int ret = initGtestParameters(arg0, options);
	if (ret)
		return ret;

	testing::UnitTest::GetInstance()->listeners().Append(new ThrowListener);

	return 0;
}

static int parseOptions(int argc, char **argv, OptionsParser::Options *options)
{
	OptionsParser parser;
	parser.addOption(OptCamera, OptionString,
			 "Specify which camera to operate on, by id", "camera",
			 ArgumentRequired, "camera");
	parser.addOption(OptList, OptionNone, "List all tests and exit", "list");
	parser.addOption(OptFilter, OptionString,
			 "Specify which tests to run", "filter",
			 ArgumentRequired, "filter");
	parser.addOption(OptHelp, OptionNone, "Display this help message",
			 "help");

	*options = parser.parse(argc, argv);
	if (!options->valid())
		return -EINVAL;

	if (options->isSet(OptHelp)) {
		parser.usage();
		std::cerr << "Further options from Googletest can be passed as environment variables"
			  << std::endl;
		return -EINTR;
	}

	return 0;
}

int main(int argc, char **argv)
{
	OptionsParser::Options options;
	int ret = parseOptions(argc, argv, &options);
	if (ret == -EINTR)
		return EXIT_SUCCESS;
	if (ret < 0)
		return EXIT_FAILURE;

	std::unique_ptr<CameraManager> cm = std::make_unique<CameraManager>();

	/* No need to initialize the camera if we'll just list tests */
	if (!options.isSet(OptList)) {
		ret = initCamera(cm.get(), options);
		if (ret)
			return ret;
	}

	ret = initGtest(argv[0], options);
	if (ret)
		return ret;

	ret = RUN_ALL_TESTS();

	if (!options.isSet(OptList))
		cm->stop();

	return ret;
}
