module util.config;

import std.stdio;
import slf4d;
import asdf;

/**
 * The path of the config file to attempt to load. 
 */
private const CONFIG_FILE = "finnow-api-config.json";

/**
 * Finnow API configuration struct, which contains properties used to
 * configure various parts of the API.
 */
struct AppConfig {
	/**
	 * The port on which the HTTP server will accept requests.
	 */
	ushort port;
	/**
	 * The address at which the corresponding Finnow website is available to
	 * clients. In development, this will be another localhost address, but in
	 * deployed environments, it'll be the actual website with a legitimate
	 * domain name. This is used to supply the Access-Control-Allow-Origin
	 * CORS header, which can help to prevent cross-site-scripting attacks.
	 */
	string webOrigin;
	/**
	 * The logging level to use globally in the application. See SLF4D for more:
	 * <a>https://andrewlalis.github.io/slf4d/guide/using-slf4d.html#logging-levels</a>
	 */
	string logLevel;
}

Level getConfiguredLoggingLevel(in AppConfig cfg) {
    try {
        return parseLoggingLevel(cfg.logLevel);
    } catch (LoggingException e) {
        return Levels.INFO;
    }
}

AppConfig readConfig() {
	import std.file : exists, readText;
	import std.json;
	import std.conv : to;

	AppConfig defaultConfig = AppConfig(
		8080,
		"http://localhost:5173",
		"INFO"
	);
	// Local dev environment if no config is given.
	if (!exists(CONFIG_FILE)) {
		const defaultConfigJson = serializeToJson(defaultConfig);
		infoF!"No config file \"%s\" found. Using defaults: %s."(CONFIG_FILE, defaultConfigJson);
		return defaultConfig;
	}
    JSONValue obj;
    try {
        obj = parseJSON(readText(CONFIG_FILE));
    } catch (Exception e) {
        stderr.writefln!"Failed to read config from file %s, using default config as a fallback: %s"(
            CONFIG_FILE,
            e.msg
        );
        return defaultConfig;
    }
	if ("port" in obj.object) {
		defaultConfig.port = obj.object["port"].integer.to!ushort;
	}
	if ("webOrigin" in obj.object) {
		defaultConfig.webOrigin = obj.object["webOrigin"].str;
	}
	if ("logLevel" in obj.object) {
		defaultConfig.logLevel = obj.object["logLevel"].str;
	}
	return defaultConfig;
}