/**
 * @license
 * Copyright 2019 Balena Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * CLI entrypoint, but see also `bin/balena` and `bin/balena-dev` which
 * call this function.
 */
export async function run(
	cliArgs = process.argv,
	options: import('./preparser').AppOptions = {},
) {
	// DEBUG set to falsy for negative values else is truthy
	process.env.DEBUG = ['0', 'no', 'false', '', undefined].includes(
		process.env.DEBUG?.toLowerCase(),
	)
		? ''
		: '1';

	// The 'pkgExec' special/internal command provides a Node.js interpreter
	// for use of the standalone zip package. See pkgExec function.
	if (cliArgs.length > 3 && cliArgs[2] === 'pkgExec') {
		return pkgExec(cliArgs[3], cliArgs.slice(4));
	}

	const { globalInit } = await import('./app-common');
	const { routeCliFramework } = await import('./preparser');

	// globalInit() must be called very early on (before other imports) because
	// it sets up Sentry error reporting, global HTTP proxy settings, balena-sdk
	// shared options, and performs node version requirement checks.
	await globalInit();
	await routeCliFramework(cliArgs, options);

	// Windows fix: reading from stdin prevents the process from exiting
	process.stdin.pause();
}

/**
 * Implements the 'pkgExec' command, used as a way to provide a Node.js
 * interpreter for child_process.spawn()-like operations when the CLI is
 * executing as a standalone zip package (built-in Node interpreter) and
 * the system may not have a separate Node.js installation. A present use
 * case is a patched version of the 'windosu' package that requires a
 * Node.js interpreter to spawn a privileged child process.
 *
 * @param modFunc Path to a JS module that will be executed via require().
 * The modFunc argument may optionally contain a function name separated
 * by '::', for example '::main' in:
 * 'C:\\snapshot\\balena-cli\\node_modules\\windosu\\lib\\pipe.js::main'
 * in which case that function is executed in the require'd module.
 * @param args Optional arguments to passed through process.argv and as
 * arguments to the function specified via modFunc.
 */
async function pkgExec(modFunc: string, args: string[]) {
	const [modPath, funcName] = modFunc.split('::');
	let replacedModPath = modPath;
	const match = modPath
		.replace(/\\/g, '/')
		.match(/\/snapshot\/balena-cli\/(.+)/);
	if (match) {
		replacedModPath = `../${match[1]}`;
	}
	process.argv = [process.argv[0], process.argv[1], ...args];
	try {
		const mod: any = await import(replacedModPath);
		if (funcName) {
			await mod[funcName](...args);
		}
	} catch (err) {
		console.error(`Error executing pkgExec "${modFunc}" [${args.join()}]`);
		console.error(err);
	}
}