/* Copyright (C) 2009 Luke Shumaker
   system depends: <string.h> <error.h>
   This file is part of rvs.
   
   rvs is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your
   option) any later version.
   
   rvs is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
   See the GNU General Public License for more details.
   
   You should have received a copy of the GNU General Public License
   along with rvs; see the file COPYING.
   If not, write to the Free Software Foundation,
   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef FILE_plugin_depend_h_SEEN
#define FILE_plugin_depend_h_SEEN

#include <string.h>
#include <error.h>

#include "rvs.h"
#include "plugin-find.h"

/* translates a string in format `plugin/command' into a pointer to the command
   DON'T plan on using the string again, it will be mutilated!
    (so we go ahead and free() it and set the pointer to NULL)                */
struct plugin_command *
plugin_depend_parse (char **string,
                     struct plugin *plugins,
                     struct plugin_command *root)
{
	struct plugin_command *command=NULL;
	
	if (*string==NULL)
		command=root;
	else {
		/* *string is in the format `plugin/command' */
		/* char *del=delimeter */
		char *del=strchr(*string,'/');
		del[0]='\0';
		/*  *string =  PLUGIN_NAME */
		/*  &del[1] = COMMAND_NAME */
		struct plugin *plugin;
		plugin =plugin_find_plugin(plugins,                  *string );
		if (plugin==NULL)
			error(EXIT_FAILURE,0,"cannot find plugin `%s'",*string);
		command=plugin_find_plugin_command(plugin->commands, &del[1] );
		if (command==NULL)
			error(EXIT_FAILURE,0,
				"plugin `%s' does not contain command `%s'",
				*string,&del[1]);
		xfree(*string);
		*string=NULL;
	}
	return command;
}

/* used by plugin_depend_add */
void
_plugin_depend_add (struct plugin_command *prev,
                    struct plugin_command *next)
{
	if (prev->d_next==NULL) {
	    prev->d_next=next;
	} else {
		_plugin_depend_add(prev->d_next,next);
	}
}

/* plugin_depend_add(depend,depender) */
void
plugin_depend_add (struct plugin_command *depend,
                   struct plugin_command *depender)
{
	if (depend->d_child==NULL) {
	    depend->d_child=depender;
	} else {
		_plugin_depend_add(depend->d_child,depender);
	}
}

/* take care of depends for `command' */
void
plugin_depend_command (struct plugin_command *command,
                       struct plugin *plugins,
                       struct plugin_command *root, int ind)
{
	if (command!=NULL) {
		if (command->depend == NULL) {
			/* the depend still needs to be parsed */
			command->depend=plugin_depend_parse(
				&(command->depends),plugins,root);
		}
		plugin_depend_add(command->depend,command);
	}
}

/* take care of commands for a `plugin', and those after it (linked list) */
void
plugin_depend_plugin_all (struct plugin *plugin,
                          struct plugin *plugins,
                          struct plugin_command *root)
{
	plugin_depend_command(plugin->commands,plugins,root,0);
	if (plugin->next != NULL) {
		plugin_depend_plugin_all(plugin->next,plugins,root);
	}
}

/* take care of all depends */
struct plugin_command *
plugin_depend_all (struct plugin *plugins)
{
	struct plugin_command *root=plugin_mk_command();
	
	plugin_depend_plugin_all(plugins,plugins,root);
	return root;
}

void
_plugin_depend_list (struct plugin_command_list *commands,
                     struct plugin *plugins,
                     struct plugin_command *root,int ind)
{
	if (commands!=NULL) {
		plugin_depend_command(commands->command,plugins,root,ind++);
		_plugin_depend_list(commands->next,plugins,root,ind++);
	}
}

struct plugin_command *
plugin_depend_list (struct plugin_command_list *commands,
                    struct plugin *plugins)
{
	struct plugin_command *root=plugin_mk_command();
	_plugin_depend_list(commands,plugins,root,0);
	return root;
}

#endif