/**********************************************************************
 * LeechCraft - modular cross-platform feature rich internet client.
 * Copyright (C) 2006-2014  Georg Rudoy
 *
 * Boost Software License - Version 1.0 - August 17th, 2003
 *
 * Permission is hereby granted, free of charge, to any person or organization
 * obtaining a copy of the software and accompanying documentation covered by
 * this license (the "Software") to use, reproduce, display, distribute,
 * execute, and transmit the Software, and to prepare derivative works of the
 * Software, and to permit third-parties to whom the Software is furnished to
 * do so, all subject to the following:
 *
 * The copyright notices in the Software and this entire statement, including
 * the above license grant, this restriction and the following disclaimer,
 * must be included in all copies of the Software, in whole or in part, and
 * all derivative works of the Software, unless such copies or derivative
 * works are solely in the form of machine-executable object code generated by
 * a source language processor.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
 * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
 * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 **********************************************************************/

#include <stdexcept>
#include <thread>
#include <cstdlib>
#include <iostream>

#ifndef Q_MOC_RUN // see https://bugreports.qt-project.org/browse/QTBUG-22829
#include <boost/program_options.hpp>
#endif

#include <QApplication>
#include "appinfo.h"
#include "crashdialog.h"

namespace CrashProcess = LeechCraft::AnHero::CrashProcess;

namespace
{
	namespace bpo = boost::program_options;

	void ShowHelp (const bpo::options_description& desc)
	{
		std::cout << "LeechCraft (https://leechcraft.org)" << std::endl;
		std::cout << std::endl;
		std::cout << "This is the crash handler process and it is not "
				<< "intended to be run manually." << std::endl;
		std::cout << std::endl;
		std::cout << desc << std::endl;
		std::exit (3);
	}

	CrashProcess::AppInfo ParseOptions (int argc, char **argv)
	{
		bpo::options_description desc ("Known options");
		desc.add_options ()
				("signal", bpo::value<int> (), "the signal that triggered the crash handler")
				("pid", bpo::value<uint64_t> ()->required (), "the PID of the crashed process")
				("path", bpo::value<std::string> ()->required (), "the application path of the crashed process")
				("version", bpo::value<std::string> ()->required (), "the LeechCraft version at the moment of the crash")
				("suggest_restart", bpo::value<int> (), "suggest restarting LeechCraft (0 or 1)")
				("cmdline", bpo::value<std::string> (), "the command line LeechCraft was started with")
				("help", "show help message");

		bpo::command_line_parser parser (argc, argv);
		bpo::variables_map vm;
		bpo::store (parser
				.options (desc)
				.allow_unregistered ()
				.run (), vm);

		if (vm.count ("help"))
			ShowHelp (desc);

		try
		{
			bpo::notify (vm);
		}
		catch (const bpo::required_option& e)
		{
			std::cout << "required option missing" << std::endl;
			std::cout << e.what () << std::endl;

			ShowHelp (desc);
		}
		catch (const bpo::error& e)
		{
			std::cout << "invalid options" << std::endl;
			std::cout << e.what () << std::endl;

			ShowHelp (desc);
		}

		return
		{
			vm ["signal"].as<int> (),
			vm ["pid"].as<uint64_t> (),
			QString::fromUtf8 (vm ["path"].as<std::string> ().c_str ()),
			vm ["version"].as<std::string> ().c_str (),
			vm ["cmdline"].as<std::string> ().c_str (),
			vm ["suggest_restart"].as<int> () != 0
		};
	}
}

int main (int argc, char **argv)
{
	QApplication app (argc, argv);

	const auto& info = ParseOptions (argc, argv);

	new CrashProcess::CrashDialog (info);
	return app.exec ();
}
