#include "blitz/misc/Format.h"
#include "blitz/misc/Log.h"
#include "server/Server.h"
#include <iostream>

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

using namespace blitz::utils;

static std::vector<Argument> CMD_ARGUMENTS = {
	{"-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:
	blitz::server::Server& m_Server;
	std::thread m_Thread;
	bool m_Running = true;

  public:
	ConsoleThread(blitz::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(std::uint16_t port) {
	blitz::server::Server server;

	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[]) {
	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;
		}
	}

	StartServer(port);

	return EXIT_SUCCESS;
}