/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/***************************************************************************
 *            rcgen.cc
 *
 *  Sun Mar 17 20:27:17 CET 2013
 *  Copyright 2013 Bent Bisballe Nyeng
 *  deva@aasimon.org
 ****************************************************************************/

/*
 *  This file is part of DrumGizmo.
 *
 *  DrumGizmo is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  DrumGizmo is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with DrumGizmo; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
 */
#include <stdio.h>
#include <string>
#include <unistd.h>
#include <sstream>

#include <getoptpp.hpp>

std::string usage(const std::string& name, bool brief = false)
{
	std::ostringstream output;
	output <<
		"Usage: " << name << " [options]\n";
	if(!brief)
	{
		output <<
			"\n"
			"Create resource file from list of input files.\n"
			"\n";
	}
	return output.str();
}

int main(int argc, char *argv[])
{
	bool verbose{false};
	std::vector<std::string> stripPrefixes;
	std::string dirRoot;
	std::string outfile;

	dg::Options opt;

	opt.add("strip-path", required_argument, 's',
	        "Strip supplied path prefix from resource names.",
	        [&]()
	        {
		        stripPrefixes.push_back(optarg);
		        return 0;
	        });

	opt.add("dir-root", required_argument, 'd',
	        "Change to supplied root dir before reading files.",
	        [&]()
	        {
		        dirRoot = optarg;
		        return 0;
	        });

	opt.add("output", required_argument, 'o',
	        "Write output to specificed file, defaults to stdout.",
	        [&]()
	        {
		        outfile = optarg;
		        return 0;
	        });

	opt.add("verbose", no_argument, 'v',
	        "Print verbose output during processing.",
	        [&]()
	        {
		        verbose = true;
		        return 0;
	        });

	opt.add("help", no_argument, 'h',
	        "Print this message and exit.",
	        [&]()
	        {
		        std::cout << usage(argv[0]);
		        std::cout << "Options:\n";
		        opt.help();
		        exit(0);
		        return 0;
	        });

	if(opt.process(argc, argv) != 0)
	{
		return 1;
	}

	FILE* out = stdout;
	if(!outfile.empty())
	{
		out = fopen(outfile.data(), "wb");
		if(!out)
		{
			fprintf(stderr, "Could not write to file '%s' - quitting\n",
			        outfile.data());
			return 1;

		}
	}

	fprintf(out, "/* This file is autogenerated by rcgen. Do not modify! */\n");
	fprintf(out, "#include \"resource_data.h\"\n");
	fprintf(out, "\n");
	fprintf(out, "const rc_data_t rc_data[] =\n");
	fprintf(out, "{\n");

	if(!dirRoot.empty())
	{
		if(verbose)
		{
			fprintf(stderr, "Change to dir: %s\n", dirRoot.data());
		}

		if(chdir(dirRoot.data()))
		{
			return 1;
		}
	}

	for(const auto& arg : opt.arguments())
	{
		std::string resourceName = arg;
		for(const auto& stripPrefix : stripPrefixes)
		{
			if(stripPrefix == resourceName.substr(0, stripPrefix.length()))
			{
				resourceName = resourceName.substr(stripPrefix.length());
				break;
			}
		}

		fprintf(out, "	{\n		\":%s\", ", resourceName.data());

		if(verbose)
		{
			fprintf(stderr, "Process: %s\n", arg.data());
		}

		std::string data;
		FILE *fp = fopen(arg.data(), "rb");
		if(!fp)
		{
			fprintf(stderr, "Could not read file '%s' - quitting\n", arg.data());
			return 1;
		}

		char buf[32];
		while(!feof(fp))
		{
			std::size_t sz = fread(buf, 1, sizeof(buf), fp);
			data.append(buf, sz);
		}
		fclose(fp);

		fprintf(out, "%d,\n		\"", (int)data.length());
		for(std::size_t j = 0; j < data.length(); ++j)
		{
			if((j != 0) && (j % 16) == 0)
			{
				fprintf(out, "\"\n		\"");
			}
			fprintf(out, "\\%o", (unsigned char)data[j]);
		}

		fprintf(out, "\"\n	},\n");
	}

	fprintf(out, "	{ \"\", 0, 0 }\n");
	fprintf(out, "};\n");

	return 0;
}