#include <fstream>
#include <iostream>
#include <vector>
#include <iterator>
#include <string>
#include <iomanip>

int main(int argc, char * argv[])
{
	if (argc != 5)
	{
		std::cerr << "Usage: resource-compiler <input-file> <name> <output-header> <output-source>" << std::endl;
		return EXIT_FAILURE;
	}

	std::string fullname = argv[2];
	std::string name = fullname;
	std::string ns;

	std::size_t const last_slash = name.find_last_of('/');

	if (last_slash != std::string::npos)
	{
		ns = name.substr(0, last_slash);
		for (std::size_t i = 0;;)
		{
			i = ns.find('/', i);
			if (i == std::string::npos) break;
			ns.replace(i, 1, "::");
		}

		name = name.substr(last_slash + 1);
	}

	std::string tab;
	if (!ns.empty()) tab = "\t";

	std::ifstream input_file{argv[1], std::ios::binary};
	std::vector<char> input_data{std::istreambuf_iterator<char>{input_file}, {}};
	input_file.close();

	std::ofstream output_header{argv[3]};

	output_header
		<< "#pragma once\n"
		<< "\n"
		<< "#include <psemek/rs/resource.hpp>\n"
		<< "\n";

	if (!ns.empty()) output_header
		<< "namespace " << ns << "\n"
		<< "{\n"
		<< "\n";

	output_header << tab << "extern ::psemek::rs::resource const & " << name << ";\n";

	if (!ns.empty()) output_header
		<< "\n"
		<< "}\n";

	output_header.close();

	std::ofstream output_source{argv[4]};

	output_source
		<< "#include <psemek/rs/registry.hpp>\n"
		<< "\n";

	output_source << "alignas(16) static const char data[" << input_data.size() << "] = {\n";

	for (std::size_t i = 0; i < input_data.size(); ++i)
	{
		if ((i % 16) == 0) output_source << "\t";

		char const c = input_data[i];

		if constexpr (std::is_signed_v<char>)
		{
			output_source << (c >= 0 ? ' ' : '-') << "0x" << std::setw(2) << std::setfill('0') << std::hex << std::abs(static_cast<int>(c)) << ", ";
		}
		else
		{
			output_source << "0x" << std::setw(2) << std::setfill('0') << std::hex << static_cast<int>(c) << ", ";
		}


		if ((i % 16) == 15) output_source << "\n";
	}
	if ((input_data.size() % 16) != 0) output_source << "\n";

	output_source << "};\n\n";

	if (!ns.empty()) output_source
		<< "namespace " << ns << "\n"
		<< "{\n"
		<< "\n";

	output_source << tab << "::psemek::rs::resource const & " << name << " = ::psemek::rs::get(::psemek::rs::add(\"" << fullname << "\", {data, sizeof(data)}));\n";

	if (!ns.empty()) output_source
		<< "\n"
		<< "}\n";
}
