#pragma once

#include "Core/Io/Url.h"
#include "Core/Array.h"

namespace storm {
	STORM_PKG(core.sys);

	// Open an `Url` using the default program that is associated with the file in the operating
	// system. Throws a `SystemError` on failure.
	void STORM_FN open(Url *file);

	// Execute the program `program` with the parameters in `args`. If `program` is a relative url
	// that consists of a single part, then the function searches for the program in the `PATH`
	// environment variable.
	//
	// Equivalent to `Execute(program, params).detach()`.
	void STORM_FN execute(Url *program, Array<Str *> *args);


	/**
	 * More complex process-execution interface. Allows managing process creation at a finer level
	 * without complicating the API when more functionality is required.
	 *
	 * The class is designed so that it is possible to chain calls (e.g. `Execute(...).workingDirectory(...).detach()`)
	 */
	class Execute : public Object {
		STORM_CLASS;
	public:
		// Create an instance, specify program name and command-line arguments. If `program` is a
		// relative url that consists of a single path the function searches for the program in the
		// `PATH` environment variable.
		STORM_CTOR Execute(Url *program, Array<Str *> *args);

		// Create an instance, specify name and command-line arguments. Assumes `program` to be
		// found in the `PATH` environment variable.
		STORM_CTOR Execute(Str *program, Array<Str *> *args);

		// Set the working directory.
		Execute *STORM_FN workingDirectory(MAYBE(Url *) dir);

		// Start the program in a new terminal window (implies a new process group).
		// - On Windows: this is only done if the started program is a console application.
		// - On Linux: this always launches a new terminal using `xdg-terminal-exec` if available.
		Execute *STORM_FN newTerminal();

		// Start the program in a new process group. Mostly relevant for terminal-based applications.
		Execute *STORM_FN newGroup();

		// Execute the program and detach it from the current process (i.e., we will not wait for
		// it, nor interact with stdin/stdout).
		void STORM_FN detach();

	private:
		// Program name.
		Url *program;

		// Arguments.
		Array<Str *> *args;

		// Set working directory.
		MAYBE(Url *) workingDir;

		// Start in a separate terminal window.
		Bool terminal;

		// New process group?
		Bool group;

		// Give access to the internals.
		friend void platformExecute(Execute *);
	};

}
