/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * Copyright (C) 2018, Google Inc.
 *
 * utils.cpp - Miscellaneous utility tests
 */

#include <iostream>
#include <map>
#include <sstream>
#include <string>
#include <vector>

#include <libcamera/base/span.h>
#include <libcamera/base/utils.h>

#include <libcamera/geometry.h>

#include "test.h"

using namespace std;
using namespace libcamera;
using namespace std::literals::chrono_literals;

class UtilsTest : public Test
{
protected:
	int testDirname()
	{
		static const std::vector<std::string> paths = {
			"",
			"///",
			"/bin",
			"/usr/bin",
			"//etc////",
			"//tmp//d//",
			"current_file",
			"./current_file",
			"./current_dir/",
			"current_dir/",
		};

		static const std::vector<std::string> expected = {
			".",
			"/",
			"/",
			"/usr",
			"/",
			"//tmp",
			".",
			".",
			".",
			".",
		};

		std::vector<std::string> results;

		for (const auto &path : paths)
			results.push_back(utils::dirname(path));

		if (results != expected) {
			cerr << "utils::dirname() tests failed" << endl;

			cerr << "expected: " << endl;
			for (const auto &path : expected)
				cerr << "\t" << path << endl;

			cerr << "results: " << endl;
			for (const auto &path : results)
				cerr << "\t" << path << endl;

			return TestFail;
		}

		return TestPass;
	}

	int testEnumerate()
	{
		std::vector<unsigned int> integers{ 1, 2, 3, 4, 5 };
		unsigned int i = 0;

		for (auto [index, value] : utils::enumerate(integers)) {
			if (index != i || value != i + 1) {
				cerr << "utils::enumerate(<vector>) test failed: i=" << i
				     << ", index=" << index << ", value=" << value
				     << std::endl;
				return TestFail;
			}

			/* Verify that we can modify the value. */
			--value;
			++i;
		}

		if (integers != std::vector<unsigned int>{ 0, 1, 2, 3, 4 }) {
			cerr << "Failed to modify container in enumerated range loop" << endl;
			return TestFail;
		}

		Span<const unsigned int> span{ integers };
		i = 0;

		for (auto [index, value] : utils::enumerate(span)) {
			if (index != i || value != i) {
				cerr << "utils::enumerate(<span>) test failed: i=" << i
				     << ", index=" << index << ", value=" << value
				     << std::endl;
				return TestFail;
			}

			++i;
		}

		const unsigned int array[] = { 0, 2, 4, 6, 8 };
		i = 0;

		for (auto [index, value] : utils::enumerate(array)) {
			if (index != i || value != i * 2) {
				cerr << "utils::enumerate(<array>) test failed: i=" << i
				     << ", index=" << index << ", value=" << value
				     << std::endl;
				return TestFail;
			}

			++i;
		}

		return TestPass;
	}

	int testDuration()
	{
		std::ostringstream os;
		utils::Duration exposure;
		double ratio;

		exposure = 25ms + 25ms;
		if (exposure.get<std::micro>() != 50000.0) {
			cerr << "utils::Duration failed to return microsecond count";
			return TestFail;
		}

		exposure = 1.0s / 4;
		if (exposure != 250ms) {
			cerr << "utils::Duration failed scalar divide test";
			return TestFail;
		}

		exposure = 5000.5us;
		if (!exposure) {
			cerr << "utils::Duration failed boolean test";
			return TestFail;
		}

		os << exposure;
		if (os.str() != "5000.50us") {
			cerr << "utils::Duration operator << failed";
			return TestFail;
		}

		exposure = 100ms;
		ratio = exposure / 25ms;
		if (ratio != 4.0) {
			cerr << "utils::Duration failed ratio test";
			return TestFail;
		}

		return TestPass;
	}

	int run()
	{
		/* utils::hex() test. */
		std::ostringstream os;
		std::string ref;

		os << utils::hex(static_cast<int32_t>(0x42)) << " ";
		ref += "0x00000042 ";
		os << utils::hex(static_cast<uint32_t>(0x42)) << " ";
		ref += "0x00000042 ";
		os << utils::hex(static_cast<int64_t>(0x42)) << " ";
		ref += "0x0000000000000042 ";
		os << utils::hex(static_cast<uint64_t>(0x42)) << " ";
		ref += "0x0000000000000042 ";
		os << utils::hex(static_cast<int32_t>(0x42), 4) << " ";
		ref += "0x0042 ";
		os << utils::hex(static_cast<uint32_t>(0x42), 1) << " ";
		ref += "0x42 ";
		os << utils::hex(static_cast<int64_t>(0x42), 4) << " ";
		ref += "0x0042 ";
		os << utils::hex(static_cast<uint64_t>(0x42), 1) << " ";
		ref += "0x42 ";

		std::string s = os.str();
		if (s != ref) {
			cerr << "utils::hex() test failed, expected '" << ref
			     << "', got '" << s << "'";
			return TestFail;
		}

		/* utils::join() and utils::split() test. */
		std::vector<std::string> elements = {
			"/bin",
			"/usr/bin",
			"",
			"",
		};

		std::string path;
		for (const auto &element : elements)
			path += (path.empty() ? "" : ":") + element;

		if (path != utils::join(elements, ":")) {
			cerr << "utils::join() test failed" << endl;
			return TestFail;
		}

		std::vector<std::string> dirs;

		for (const auto &dir : utils::split(path, ":"))
			dirs.push_back(dir);

		if (dirs != elements) {
			cerr << "utils::split() test failed" << endl;
			return TestFail;
		}

		/* utils::join() with conversion function test. */
		std::vector<Size> sizes = { { 0, 0 }, { 100, 100 } };
		s = utils::join(sizes, "/", [](const Size &size) {
					return size.toString();
				});

		if (s != "0x0/100x100") {
			cerr << "utils::join() with conversion test failed" << endl;
			return TestFail;
		}

		/* utils::dirname() tests. */
		if (TestPass != testDirname())
			return TestFail;


		/* utils::map_keys() test. */
		const std::map<std::string, unsigned int> map{
			{ "zero", 0 },
			{ "one", 1 },
			{ "two", 2 },
		};
		std::vector<std::string> expectedKeys{
			"zero",
			"one",
			"two",
		};

		std::sort(expectedKeys.begin(), expectedKeys.end());

		const std::vector<std::string> keys = utils::map_keys(map);
		if (keys != expectedKeys) {
			cerr << "utils::map_keys() test failed" << endl;
			return TestFail;
		}

		/* utils::alignUp() and utils::alignDown() tests. */
		if (utils::alignDown(6, 3) != 6 || utils::alignDown(7, 3) != 6) {
			cerr << "utils::alignDown test failed" << endl;
			return TestFail;
		}

		if (utils::alignUp(6, 3) != 6 || utils::alignUp(7, 3) != 9) {
			cerr << "utils::alignUp test failed" << endl;
			return TestFail;
		}

		/* utils::enumerate() test. */
		if (testEnumerate() != TestPass)
			return TestFail;

		/* utils::Duration test. */
		if (testDuration() != TestPass)
			return TestFail;

		return TestPass;
	}
};

TEST_REGISTER(UtilsTest)
