/*
 *	Helper API for N-way trees.
 */

/*
 * There are 8 possible ways to traverse. Desired way can be selected
 * by specifying following flags:
 *  - flag1: process all leafs, than root;
 *	- flag2: process from leftmost to rightmost sibling;
 *	- flag3: process from root's leafs (wtf was i mean ???)
 */

void	V_CALL /* this is default, so it should be non-local (FIXME?) */
traverse_lf_lf_uf(tree_traverse_proc_t self,ntree_p node,void *node_data,
	void (V_CALL *handler)(void*))
{
}

V_LOCAL	void	V_CALL
traverse_rf_lf_uf(tree_traverse_proc_t self,ntree_p node,void *node_data,
	void (V_CALL *handler)(void*))
{
}

V_LOCAL	void	V_CALL
traverse_lf_rf_uf(tree_traverse_proc_t self,ntree_p node,void *node_data)
{
}

V_LOCAL	void	V_CALL
traverse_rf_rf_uf(tree_traverse_proc_t self,ntree_p node,void *node_data)
{
}

V_LOCAL	void	V_CALL
traverse_lf_lf_df(tree_traverse_proc_t self,ntree_p node,void *node_data)
{
}

V_LOCAL	void	V_CALL
traverse_rf_lf_df(tree_traverse_proc_t self,ntree_p node,void *node_data)
{
}

V_LOCAL	void	V_CALL
traverse_lf_rf_df(tree_traverse_proc_t self,ntree_p node,void *node_data)
{
}

V_LOCAL	void	V_CALL
traverse_rf_rf_df(tree_traverse_proc_t self,ntree_p node,void *node_data)
{
}

V_LOCAL	void	V_CALL
treeTraverseFromRight_r(ntree_t *root,void (V_CALL *proc)(void*))
{
	u32_t ind,count;
	ntree_p *ch;
	if(!root)
		return;
	proc(root->data);
	ch=(ntree_p*)vpsGetStorage(&root->children);
	count=vpsCount(&root->children);
	if(!count)
		return;
	for(ind=count-1;;ind--)
	{
		treeTraverseFromRight_r(ch[ind],proc);
		if(!ind)
			return;
	}
}

V_LOCAL	void	V_CALL
treeTraverseFromLeftDU_r(ntree_t *root,void (V_CALL *proc)(void*))
{
	u32_t ind,count;
	ntree_p *ch;
	if(!root)
		return;
	ch=(ntree_p*)vpsGetStorage(&root->children);
	count=vpsCount(&root->children);
	for(ind=0;ind<count;ind++)
		treeTraverseFromLeftDU_r(ch[ind],proc);
	proc(root->data);
}

V_LOCAL	void	V_CALL
treeTraverseFromRightDU_r(ntree_t *root,void (V_CALL *proc)(void*))
{
	u32_t ind,count;
	ntree_p *ch;
	if(!root)
		return;
	ch=(ntree_p*)vpsGetStorage(&root->children);
	count=vpsCount(&root->children);
	if(!count)
		return;
	for(ind=count-1;;ind--)
	{
		treeTraverseFromRightDU_r(ch[ind],proc);
		if(!ind)
			break;
	}
	proc(root->data);
}

#error HERE

V_LOCAL	void	V_CALL
treeTraverseFromLeftRF_r(ntree_t *root,void (V_CALL *proc)(void*))
{
	u32_t ind,count;
	ntree_p *ch;
	if(!root)
		return;
	ch=(ntree_p*)vpsGetStorage(&root->children);
	count=vpsCount(&root->children);
	for(ind=0;ind<count;ind++)
		proc(ch[ind]->data);
	for(ind=0;ind<count;ind++)
		treeTraverseFromLeftRF_r(ch[ind],proc);
}

V_LOCAL	void	V_CALL
treeTraverseFromRightRF_r(ntree_t *root,void (V_CALL *proc)(void*))
{
	u32_t ind,count;
	ntree_p *ch;
	if(!root)
		return;
	ch=(ntree_p*)vpsGetStorage(&root->children);
	count=vpsCount(&root->children);
	if(!count)
		return;
	for(ind=count-1;;ind--)
	{
		proc(ch[ind]->data);
		if(!ind)
			break;
	}
	for(ind=count-1;;ind--)
	{
		treeTraverseFromRightRF_r(ch[ind],proc);
		if(!ind)
			return;
	}
}

vboolean V_LOCAL
#ifdef	CHECKED_BUILD
ntree_check_traverse_args(char *caller,ntree_t *node,void (V_CALL *proc)(void*))
{
	if(!node)
	{
		conlPrintf(LOG_ERROR,"%s(): nothing to traverse.\n",
			caller);
		return false;
	}
	if(!proc)
	{
		conlPrintf(LOG_ERROR,"%s(): nothing to do with nodes.\n",
			caller);
		return false;
	}
	return true;
}
#else	/* !CHECKED_BUILD */
ntree_check_traverse_args_q(btree_t *node,void (V_CALL *proc)(void*))
{
	return (!node || !proc) ? 0 : 1;
}
#define	ntree_check_traverse_args(caller,node,proc)	\
		ntree_check_traverse_args_q(node,proc)
#endif


/*
 * List of traverse procs
 */
V_LOCAL	tree_traverse_proc_t	libv_tree_traverse_procs[]=
{
	traverse_lf_lf_uf,
	traverse_rf_lf_uf,
	traverse_lf_rf_uf,
	traverse_rf_rf_uf,
	traverse_lf_lf_df,
	traverse_rf_lf_df,
	traverse_lf_rf_df,
	traverse_rf_rf_df
};

vboolean	V_GLOBAL
treeTraverseMode(tree_traverse_t bits_to_set,vboolean set_bit)
{
	thread_data_t *td;
	u32_t bitmask = 0, bits;
	if(bits_to_set & TREE_FROM_LEAFS_BIT)
		bitmask |= 1;
	if(bits_to_set & TREE_FROM_LEFT_BIT)
		bitmask |= 2;
	if(bits_to_set & TREE_FROM_UP_BIT)
		bitmask |= 4;
	td=GetThreadData();
	bits = td->tree_traverse_mode;
	if(set_bit)
		bits |= bitmask; 
	else
		bits &= ~bitmask;
	td->tree_traverse_mode = bits;
	td->tree_traverse_proc = libv_tree_traverse_procs[bits];
	return true;
}

typedef	void (V_CALL *tree_traverse_proc)(tree_traverse_proc*,ntree_p,void (V_CALL *handler)(void));

/*
in thread_data_t:
	tree_traverse_proc_t traverse_proc;
*/

