#include "../../include/dv-processing/io/camera/parsers/s5k231y_parser.hpp"
#include "../../include/dv-processing/io/camera/parsers/s5krc1s_parser.hpp"
#include "../../include/dv-processing/io/simplefile.hpp"

#include <benchmark/benchmark.h>

#include <iostream>

static std::vector<uint8_t> S5K231Y_DATA;
static std::vector<uint8_t> S5KRC1S_DATA;

void bmS5K231Y(benchmark::State &state) {
	size_t inputElements{0};
	size_t processedElements{0};

	for (auto _ : state) {
		dv::io::camera::parser::S5K231Y::Parser parser;
		parser.setLogger([](bool debug, std::string_view message) {
		});

		parser.setDataCommitCallback([&processedElements](const dv::io::camera::parser::ParsedData buffers) {
			processedElements += buffers.events.elements.size();
		});

		inputElements += S5K231Y_DATA.size();
		parser.parseData(S5K231Y_DATA, false);
	}

	state.SetItemsProcessed(static_cast<int64_t>(inputElements));
	state.SetLabel("bytes");
	state.counters["events"]
		= benchmark::Counter(static_cast<int64_t>(processedElements), benchmark::Counter::kAvgIterations);
}

void bmS5KRC1S(benchmark::State &state) {
	size_t inputElements{0};
	size_t processedElements{0};

	for (auto _ : state) {
		dv::io::camera::parser::S5KRC1S::Parser parser;
		parser.setLogger([](bool debug, std::string_view message) {
		});

		parser.setDataCommitCallback([&processedElements](const dv::io::camera::parser::ParsedData buffers) {
			processedElements += buffers.events.elements.size();
		});

		inputElements += S5KRC1S_DATA.size();
		parser.parseData(S5KRC1S_DATA, false);
	}

	state.SetItemsProcessed(static_cast<int64_t>(inputElements));
	state.SetLabel("bytes");
	state.counters["events"]
		= benchmark::Counter(static_cast<int64_t>(processedElements), benchmark::Counter::kAvgIterations);
}

int main(int argc, char **argv) {
	std::cout << "-- Loading data ..." << std::endl;

	{
		const dv::io::SimpleReadOnlyFile s5k231yFile{std::filesystem::path{"s5k231y.raw"}};

		S5K231Y_DATA = s5k231yFile.readAll();
		S5K231Y_DATA.shrink_to_fit();
	}

	{
		const dv::io::SimpleReadOnlyFile s5krc1sFile{std::filesystem::path{"s5krc1s.raw"}};

		S5KRC1S_DATA = s5krc1sFile.readAll();
		S5KRC1S_DATA.shrink_to_fit();
	}

	std::cout << "-- Loaded data." << std::endl;

	BENCHMARK(bmS5K231Y);
	BENCHMARK(bmS5KRC1S);

	::benchmark::Initialize(&argc, argv);
	if (::benchmark::ReportUnrecognizedArguments(argc, argv)) {
		return EXIT_FAILURE;
	}
	::benchmark::RunSpecifiedBenchmarks();

	return EXIT_SUCCESS;
}
