const semver = require("semver");
const { exec } = require("child_process");
const pkg = require("../package.json");


function compatible () {
	return Promise.all([
		compatible_schema(),
		compatible_api()
	]);
}

/** Report whether the database schema version is
 * compatible with the version required by this server.
 *
 * The current schema version is retrieved from the
 * public.info table.
 *
 * The wanted version is retrieved from package.json
 * (config.db_schema).
 *
 * @returns true if the versions are compatible,
 * false otherwise.
 */
function compatible_schema () {
	const { info } = require('./db');
	return new Promise ( async (resolve, reject) => {
		const current = await info.get(null, "version/db_schema");
		const wanted = pkg.config.db_schema;
		const component = "schema";
		if (semver.satisfies(current, wanted)) {
			resolve({current, wanted, component});
		} else {
			reject({current, wanted, component});
		}
	});
}

function compatible_api () {
	const api = require('../api');
	return new Promise ( async (resolve, reject) => {
		const current = api.locals.version;
		const wanted = pkg.config.api;
		const component = "api";
		if (semver.satisfies(current, wanted)) {
			resolve({current, wanted, component});
		} else {
			reject({current, wanted, component});
		}
	});
}


/** Return software name.
 *
 */
function name () {
	const pkg = require("../package.json");
	return pkg.name ?? pkg.description ?? "Unknown";
}

/** Return software version, from Git if possible.
 *
 */
async function describe () {
	return new Promise( (resolve, reject) => {
		const cmd = `git describe || echo git+$(git describe --always);`;
		exec(cmd, {cwd: __dirname}, (error, stdout, stderr) => {
			if (error) {
				reject(error);
			}

			if (stdout) {
				resolve(stdout.trim());
			} else {
				// Most likely not installed from Git, use the
				// version number in package.json.
				resolve(pkg.version ?? "Unknown")
			}
		})
	});
}

function version () {
	return pkg.version;
}
version.compatible = compatible;
version.name = name;
version.describe = describe;

module.exports = version;
