/* Given a command trie, look up the action that matches the input
 * passed as an array of input strings (typically argv).  The input
 * array and number of items in the array (num) are passed as
 * pointers, such that they are updated to the position of the
 * matched action.
 * The matching action (if any) is stored in the action pointer, and
 * the state of the matching is returned by the function:
 * NONE    - command mismatch
 * ACTION  - matched an action, arguments might remain in input
 * SUBTRIE - matched a "parent command", with available subcommands
 *
 * If auto_complete is TRUE, unambiguous prefixes of commands are
 * automatically matched.
 *
 * If completions is not NULL, a list of possible completions is
 * stored in it.
 */
command_trie_match_type_t
command_trie_find (command_trie_t *trie, gchar ***input, gint *num,
                   gboolean auto_complete, command_action_t **action,
                   GList **completions)
{
	command_trie_t *node;
	command_trie_match_type_t retval = COMMAND_TRIE_MATCH_NONE;

	if ((node = command_trie_find_node (trie, **input, auto_complete, completions))) {
		(*input) ++;
		(*num) --;
		if (node->match.type == COMMAND_TRIE_MATCH_ACTION) {
			*action = node->match.action;
			retval = COMMAND_TRIE_MATCH_ACTION;
		} else if (node->match.type == COMMAND_TRIE_MATCH_SUBTRIE) {
			if (*num == 0) {
				*action = node->match.action;
				retval = COMMAND_TRIE_MATCH_SUBTRIE;
			} else {
				retval = command_trie_find (node->match.subtrie, input, num,
				                            auto_complete, action, completions);
			}
		}
	}

	return retval;
}
static command_trie_t *
command_trie_find_node (command_trie_t *trie, gchar *input,
                        gboolean auto_complete)
{
	command_trie_t *node = NULL;
	GList *l;

	/* FIXME: If this happens when a parent command is given, make it nice! */
	if (input == NULL) {
		return NULL;
	}

	if (*input == 0) {
		/* End of token, return current action, or unique completion */
		if (command_trie_valid_match (trie)) {
			node = trie;
		} else if (auto_complete) {
			node = command_trie_find_leaf (trie);
		}
	} else {
		/* Recurse in next trie node */
		l = g_list_find_custom (trie->next, input, command_trie_elem_cmp);
		if (l != NULL) {
			node = command_trie_find_node ((command_trie_t *) l->data, input + 1,
			                               auto_complete);
		}
	}

	return node;
}