/* Copyright (c) 2000-2006 ActiveState Software Inc.
   See the file LICENSE.txt for licensing information. */

/*
INVOCATIONS:

An invocation is a technique for executing different "categories" of programs.
For example, we may have a Python category, a Perl category, "Batch File"
category, etc. The Python category knows how to "build" Python programs, "run"
Python programs, and "run for debug" these same programs. In the case of
Perl/Python etc, the "build" step is a nop - indeed, no one has implemented
building at time of writing.

Invocations use "property sets" to handle all optional information. For example,
you can specify the main script entry point, and arguments to the script by
setting specially named properties in the property set. Each invocation is
capable of providing a "default" set of properties, and also validating property
sets to ensure all information needed by this invocation is provided.

A default property set is generally _not_ suitable for immediate execution.
For the Perl and Python ones, for example, a "filename" property is necessary
before anything can be executed. It is the responsibility of the caller to
ensure this is set correctly. If desired, the property set for an invocation can
be persisted. Again, it is the responsibility of the caller to determine where
to persist this info.

EXAMPLE:
To create and execute a Python program, the following code would be used.
<code>

ob = components.classes["@activestate.com/koInvocation;1?type=Python"].\
     createInstance()

// get default property sets.
cat_prefs, inst_prefs = ob.getDefaultPreferences(INVOKE_RUN);

// fill in the script to be executed.
inst_prefs.setStringPref("filename", "foo.py")

// Set the properties as the properties to actually use.
ob.currentCategoryPreferences = cat_prefs
ob.currentInstancePreferences = inst_prefs

// validate the preference set (not necessary, but nice)
ok, bad_prop_id, bad_prop_message = ob.validate(INVOKE_RUN)

// setup redirection.
ob.stdout = some_file_object
ob.stdin ...

// execute the baby
ob.invoke(INVOKE_RUN)

</code>
    
TO DO AND OTHER WARTS:
* We need a decent registry of invocations.  This has been punted completely!
   Such a change would probably also change the "invocation info" interface.

* There should probably be at least 2 invocation interfaces here - one for
  the "invocation definition" and another with an "invocation invoker".
  The "definition" manages property sets etc.  The "invoker" actually
  has the mechanics for executing the program, redirecting handles. etc

* Linting etc may make sense to move into invocations.  This is not at all
  clear.  The biggest problem is that an invocation used for a program need
  not indicate what linter to use. Eg, for a Perl script, we may have a batch
  file invocation setup to run and debug it - however, we certainly don't want a
  batch file linter to be used. This needs more thought.

*/

#include "nsISupports.idl"
#include "koIPrefs.idl"
#include "nsIEnumerator.idl"
#include "koIFile.idl"

interface koITerminalHandler;  // Forward definition

// The invocation itself.  As per comments at the top of the
// file, this may want to be split into 2 or more interfaces
[scriptable, uuid(dba8a5aa-9b7b-4d54-a54a-80bbc0aefa80)]
interface koIInvocation : nsISupports {
    // These are bitmasks.
    const long INVOKE_RUN = 1;
    const long INVOKE_DEBUG = 2;
    const long INVOKE_BUILD = 4;
    const long INVOKE_INTERACTIVE = 8;
    const long INVOKE_PROFILE = 16;

    readonly attribute long invokeType;
    attribute string name;
    readonly attribute string cookie;

    attribute koIFile stdin;
    attribute koIFile stdout;
    attribute koIFile stderr;

    // When profiling, output will be saved to this location.
    readonly attribute AString profile_fileuri;

    // Sets up the hooks for proxying the io from the debugger's process
    // to and from the Komodo terminal handler (Scintilla).
    void hookIOForTerminal(in koITerminalHandler terminalHandler);

    // The types in "invoke" operations we support.
    readonly attribute long supportedInvokeTypes;

    // Will an INVOKE_BUILD actually do anything?
    // shame to have build as a special case, but not sure what else we can do.
    boolean needsBuild();

    // On termination the "invocation_terminated" notification is sent.
    // This replaces the older "addTerminationListener" mechanism.
    // See internal-docs/howto-invocations.txt for details.
    void invoke(in long invokeType);

    // validate against the current preferences.
    // "validate" means identify anything that will certainly
    // fail - eg, bad directory, file not found, etc.
    // NOTE: It is valid (but unusual) for |validate| to modify the
    // preference set (ie, "fix" things without complaining)
    // Will raise NS_ERROR_ILLEGAL_VALUE if invokeType is not supported by this invocation.
    boolean validate(in long invokeType, out string prefid, out string message);
    boolean validInterpreter(in long invokeType, out string prefid, out string message);

    // returns true if we (think we) killed the process, or false if the process is already dead.
    boolean terminate(in unsigned long exitCode, in boolean useForce);    

    // Support for preferences, which is how all data is set for the debug run.
    void getDefaultPreferences( out koIPreferenceSet categoryPrefs, out koIPreferenceSet instancePrefs);

    attribute koIPreferenceSet currentCategoryPreferences;
    attribute koIPreferenceSet currentInstancePreferences;
    // Return the currentInstancePreferences that should be persisted.
    // XXX - this is really a workaround for bug 18218, and should probably die!
    readonly attribute koIPreferenceSet persistableInstancePreferences;
    
    string getExecutable(in boolean asJSON);
};
