#!/usr/bin/node

const { ERROR, INFO, DEBUG } = require('DOUGAL_ROOT/debug')(__filename);

async function getProjectConfigurations (opts = {}) {
	const includeArchived = {includeArchived: false, ...opts};
	let projectConfigurations = {};
	try {
		const db = require('./lib/db');
		const pids = (await db.project.get())
			.filter(i => includeArchived || !i.archived)
			.map(i => i.pid);
		for (const pid of pids) {
			DEBUG(`Reading project configuration for ${pid}`);
			const cfg = await db.project.configuration.get(pid);
			projectConfigurations[pid] = cfg;
		}
	} catch (err) {
		ERROR("Failed to get project configurations");
		ERROR(err);
	}
	return projectConfigurations;
}

async function main () {
	// Check that we're running against the correct database version
	const version = require('./lib/version');
	INFO("Running version", await version.describe());
	version.compatible()
	.then( async (versions) => {
		try {
			const api = require('./api');
			const ws = require('./ws');
			const periodicTasks = require('./periodic-tasks').init();
			const { setupEventHandlers } = require('./events');

			const port = process.env.HTTP_PORT || 3000;
			const host = process.env.HTTP_HOST || "127.0.0.1";
			const path = process.env.HTTP_PATH ?? "/api";
			const server = api.start(port, host, path);
			ws.start(server);

			INFO("Versions:", versions);

			periodicTasks.start();

			const projectConfigurations = await getProjectConfigurations();
			const handlerSystem = await setupEventHandlers(projectConfigurations);

			process.on("SIGINT", async () => {
				DEBUG("Interrupted (SIGINT)");
				handlerSystem.close();
				await periodicTasks.cleanup();
				process.exit(0);
			})

			process.on("SIGHUP", async () => {
				DEBUG("Stopping (SIGHUP)");
				handlerSystem.close();
				await periodicTasks.cleanup();
				process.exit(0);
			})

			process.on('beforeExit', async () => {
				DEBUG("Preparing to exit");
				handlerSystem.close();
				await periodicTasks.cleanup();
			});

			process.on('exit', async () => {
				DEBUG("Exiting");
			});
		} catch (err) {
			ERROR(err);
			process.exit(2);
		}
	})
	.catch( ({current, wanted, component}) => {
		console.error(`Fatal error: incompatible ${component} version ${current} (wanted: ${wanted})`);
		ERROR(`Fatal error: incompatible ${component} version ${current} (wanted: ${wanted})`);
		process.exit(1);
	});
}

main();
