/*
 * Kangaroo Punch MultiPlayer Game Server Mark II
 * Copyright (C) 2020-2021  Scott Duensing
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 */


#include "os.h"
#include "console.h"
#include "stddclmr.h"
#include "server.h"
#include "rest.h"
#include "database.h"
#include "settings.h"

#include "thirdparty/ini/src/ini.h"


// Exported in os.h
uint8_t __running       = 1;
uint8_t __restAvailable = 1;


// "Config" items come from the INI file.  "Settings" are from the database.

static char     *_configServer    = NULL;
static uint16_t  _configPort      = 0;
static char     *_configDatabase  = NULL;
static char     *_configUser      = NULL;
static char     *_configPassword  = NULL;


static void configRead(char *file);
static void configWrite(char *file);


static void configRead(char *file) {
	ini_t *ini = NULL;

	// Numeric defaults.
	_configPort = 16550;

	ini = ini_load(file);
	if (ini) {
		ini_sget(ini, "SERVER",  "PORT",  "%d", &_configPort);
		_configServer   = strdup(ini_get(ini, "SERVER", "HOST"));
		_configDatabase = strdup(ini_get(ini, "SERVER", "DATA"));
		_configUser     = strdup(ini_get(ini, "SERVER", "USER"));
		_configPassword = strdup(ini_get(ini, "SERVER", "PASS"));
		ini_free(ini);
	}

	// String defaults.
	if (!_configServer)   strdup("kanga.world");
	if (!_configDatabase) strdup("kpmpgsmkii");
	if (!_configUser)     strdup("");
	if (!_configPassword) strdup("");
}


static void configWrite(char *file) {
	FILE *out = NULL;

	out = fopen(file, "w");
	if (out) {
		fprintf(out,
			"[SERVER]\n"
			"HOST=%s\n"
			"PORT=%d\n"
			"DATA=%s\n"
			"USER=%s\n"
			"PASS=%s\n",
			_configServer,
			_configPort,
			_configDatabase,
			_configUser,
			_configPassword
		);
		fclose(out);
	}

	DEL(_configServer);
	DEL(_configDatabase);
	DEL(_configUser);
	DEL(_configPassword);
}


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

	char        *configFile                        = NULL;
	char         hostname[256]                     = { 0 };

	(void)argc;

	memoryStartup(argv[0]);
	logOpenByHandle(memoryLogHandleGet());
	logWrite("%s", "Kangaroo Punch MultiPlayer Game Server Mark II\n");
	logWrite("%s", "Copyright (C) 2020-2021  Scott Duensing  scott@kangaroopunch.com\n\n");

	// Load our config.
	configFile = utilAppNameWithNewExtensionGet(argv[0], "ini");
	configRead(configFile);

	// Find our hostname.
	gethostname(hostname, 256);

	// Connect to database.
	if (!dbConnect(_configServer, _configPort, _configDatabase, _configUser, _configPassword)) {
		utilDie("Unable to connect to database.\n");
	}

	// Fetch settings needed to start server.
	if (!dbSettingsValueGet(hostname,  "maxClients",    (int32_t *)&__settingsMaxClients))    utilDie("Unable to load maxClients.\n");
	if (!dbSettingsValueGet(hostname,  "portNumber",    (int32_t *)&__settingsPortNumber))    utilDie("Unable to load portNumber.\n");
	if (!dbSettingsValueGet(hostname,  "clientVersion", (int32_t *)&__settingsClientVersion)) utilDie("Unable to load clientVersion.\n");
	if (!dbSettingsStringGet(hostname, "fileLocation",  __settingsFile, DB_CONFIG_ITEM_SIZE)) utilDie("Unable to load file location.\n");
	if (!dbSettingsStringGet(hostname, "restEndpoint",  __settingsRest, DB_CONFIG_ITEM_SIZE)) utilDie("Unable to load REST URL.\n");
	if (!dbSettingsStringGet(hostname, "restUser",      __settingsUser, DB_CONFIG_ITEM_SIZE)) utilDie("Unable to load REST user.\n");
	if (!dbSettingsStringGet(hostname, "restPassword",  __settingsPass, DB_CONFIG_ITEM_SIZE)) utilDie("Unable to load REST password.\n");

	// Start up REST.
	if (!restStartup(__settingsRest, __settingsUser, __settingsPass)) {
		logWrite("Unable to locate REST endpoint.  Web site integration disabled.\n");
		__restAvailable = 0;
	}

	clientStartup();
	serverStartup(__settingsPortNumber, __settingsMaxClients);
	logWrite("Server online.\n");

	// Run Console.
	consoleRun();

	// Console closed.  Stop server.
	__running = 0;

	// Wait for all running threads to shut down.
	logWrite("Shutting down.\n");
	serverShutdown();
	clientShutdown();

	// Shut down.
	restShutdown();
	configWrite(configFile);
	DEL(configFile);
	logWrite("Shutdown complete.\n");
	logClose();
	memoryShutdown();

	pthread_exit(NULL);
}
