#include <QApplication>
#include "server_starter.h"
#include "SH_assembly.h"
#include "SH_version.h"
#include <graphic.h>
#include <picrypt.h>
#include <qad_locations.h>
#include <piintrospection_server.h>
#include "SH_builtin.h"
#include "SH_assembly.h"
#include "SH_plugins_manager.h"
#ifndef WINDOWS
#  include <unistd.h>
#endif

using namespace PICoutManipulators;


void printUsage() {
	piCout << Bold << "SHS Server";
	piCout << Cyan << "Versions:";
	piCout << "  SHS:" << Bold << SHS_VERSION_NAME;
	piCout << "  PIP:" << Bold << PIPVersion();
	piCout << "  QAD:" << Bold << QAD_VERSION_NAME << NewLine;
	piCout << Green << Bold << "Usage:" << Default << "\"SHS_Server [-hnrc] [--no-graphics] [--reservation] [*.baf]\"";
	piCout <<                  "      " <<            "\"SHS_Server --passwd <admin-passphrase>\"" << NewLine;
	piCout << Green << Bold << "Details:";
	piCout << "-h --help         " << Green << "- display this message and exit";
	piCout << "-n --no-graphics  " << Green << "- start with hidden window (but also need some Gui QPA)";
	piCout << "-r --reservation  " << Green << "- enable reservation mechanism";
	piCout << "*.baf             " << Green << "- path to .baf file";
	piCout << "-p --passwd       " << Green << "- set admin password to \"admin-passphrase\" and exit";
	piCout << "-c --cloud        " << Green << "- show cloud name and exit";
}


void printVersion() {
	piCout << "Versions:";
	piCout << "  PIP" << PIP_VERSION_NAME;
	piCout << "   Qt" << qVersion();
	piCout << "  QAD" << QAD_VERSION_NAME;
	piCout << "  SHS" << SHS_VERSION_NAME;
	piCout << "  Ui sync" << SHS_UISYNC_VERSION;
	piCout << "  Network" << SHS_NETWORK_VERSION;
}


bool checkRoot() {
#ifndef WINDOWS
	if (getuid() == 0) {
		piCout << "Attention, root user!";
		return true;
	}
#endif
	return false;
}


int main(int argc, char * argv[]) {
	PIINTROSPECTION_START(SHS_Server)

	//initAbout();
	QApplication app(argc, argv);
	QAD_SETUP_APPLICATION;
	enableHighDPI();

	ServerStarter ss;

	PICrypt::hash("");
	PICLI cli(argc, argv);
	cli.setOptionalArgumentsCount(1);
	cli.addArgument("help");
	cli.addArgument("no-graphics");
	cli.addArgument("reservation");
	cli.addArgument("passwd", true);
	cli.addArgument("cloud");
	cli.addArgument("version");

	if (cli.hasArgument("version")) {
		printVersion();
		return 0;
	}
	if (cli.hasArgument("help")) {
		printUsage();
		return 0;
	}
	if (cli.hasArgument("passwd")) {
		checkRoot();
		PIString p = cli.argumentValue("passwd");
		ss.writePassword(passwordHash(p));
		return 0;
	}
	if (cli.hasArgument("cloud")) {
		checkRoot();
		SHAssembly ass;
		QStringList fl = ass.unpack(QAD::userPath(QAD::ltCache, "data") + ".baf");
		PIString server;
		bool found = false;
		for (const auto & f: fl) {
			if (f.endsWith(".dat")) {
				SHS::ServerData sd = loadFromFile<SHS::ServerData>(f);
				if (sd.project.propertyValueByName("cloud_enabled").toBool()) {
					server = Q2PIString(sd.project.propertyValueByName("cloud_address").toString()) + "@";
					found = true;
				}
				break;
			}
		}
		if (!found) {
			piCout << "Cloud disabled in project!";
			return 0;
		}
		piCout << (server + getThisCloudName());
		piCout << "https://shs.tools/pult/?address=" + (Q2PIString(QString(QUrl::toPercentEncoding(PI2QString(server + getThisCloudName())))));
		return 0;
	}

	printVersion();

	QString baf;
	if (!cli.optionalArguments().isEmpty())
		baf = PI2QString(cli.optionalArgument(0));
	ss.setNoGraphics(cli.hasArgument("no-graphics"));
	ss.setReservation(cli.hasArgument("reservation"));
	if (ss.isNoGraphics())
		app.setQuitOnLastWindowClosed(false);
	RUNTIME->plugins_manager = new SHPluginsManager();
	
	ss.restart(baf);
	int ret = app.exec();

	ss.close();
	delete RUNTIME->plugins_manager;
	return ret;
}
