//============================================================================
// Name        : Tower.cpp
// Author      : Persson
// Version     :
// Copyright   : Copyright
// Description : Hello World in C++, Ansi-style
//============================================================================

#if !defined(NDEBUG) && !defined(_WIN32)
#define BACKWARD_HAS_UNWIND 1
#define BACKWARD_HAS_DW 1
#endif

#include "td/misc/Backward.hpp"
#include "td/misc/Log.h"
#include "td/misc/Format.h"
#include "server/Server.h"

struct Argument {
	std::string Name;
	std::string Descritpion;
};

using namespace td::utils;

static std::vector<Argument> CMD_ARGUMENTS = {
		{ "<Map file>" , "The map to load"},
		{ "-P\t" , "The port to listen to. Default : 25565"},
		{ "--help\t", "Displays help"}
};

static void DisplayHelp() {
	LOG("Usage :");
	for (std::size_t i = 0; i < CMD_ARGUMENTS.size(); i++) {
		Argument& arg = CMD_ARGUMENTS[i];
		LOG(format("\t%s\t%s", arg.Name.c_str(), arg.Descritpion.c_str()));
	}
}

class ConsoleThread {
private:
	td::server::Server& m_Server;
	std::thread m_Thread;
	bool m_Running = true;
public:
	ConsoleThread(td::server::Server& server) : m_Server(server) {}

	void Start() {
		m_Thread = std::thread([this](){
			std::string line;
			while (m_Running) {
				getline(std::cin, line);

				if (line == "stop") {
					LOG("Stopping server ...");
					m_Server.Stop();
				} else if (line == "restart") {
					LOG("Restarting server ...");
					m_Server.Restart();
				}
				else if (line == "help") {
					LOG("use \"stop\" to stop the server");
					LOG("use \"restart\" to restart the server");
				}
			}
		});
	}

	void Stop() {
		m_Running = false;
		m_Thread.join();
	}

	~ConsoleThread() {}
};

static void StartServer(const std::string& mapPath, std::uint16_t port) {
	td::server::Server server;
	if (!server.LoadMap(mapPath)) {
		exit(EXIT_FAILURE);
	}

	ConsoleThread consoleThread{ server };
	consoleThread.Start();
	
	if (!server.Start(port, true)) {
		exit(EXIT_FAILURE);
	}

	LOG("Press Enter to coninue ...");
	consoleThread.Stop();
}


#ifdef __ANDROID__
extern "C"
#endif

int main(int argc, const char* args[]) {
#if !defined(NDEBUG)
	// setup signal handling
	backward::SignalHandling sh;
#endif

	std::string mapFilePath;
	std::uint16_t port = 25565;

	for (int i = 1; i < argc; i++) {
		std::string arg = args[i];

		if (arg == "--help") {
			DisplayHelp();
			return EXIT_SUCCESS;
		}

		if (arg == "-P") {
			i++;

			if (i >= argc) {
				LOG("You must specify a valid port !");
				return EXIT_FAILURE;
			}

			try {
				port = std::stoi(args[i]);
			} catch (std::exception& e) {
				LOG("You must specify a valid port !");
				return EXIT_FAILURE;
			}

			continue;
		}

		if (!mapFilePath.empty()) {
			LOG(format("Uknown parameter : %s !", arg.c_str()));
			return EXIT_FAILURE;
		}

		mapFilePath = arg;
	}

	StartServer(mapFilePath, port);

	return EXIT_SUCCESS;
}