/***********************************************************************/
/* Open Visualization Data Explorer                                    */
/* (C) Copyright IBM Corp. 1989,1999                                   */
/* ALL RIGHTS RESERVED                                                 */
/* This code licensed under the                                        */
/*    "IBM PUBLIC LICENSE - Open Visualization Data Explorer"          */
/***********************************************************************/

#include <dxconfig.h>


#include <dx/dx.h>
#include "background.h"
#include "graph.h"
#include "graphqueue.h"
#include "log.h"
#include "distp.h"

typedef struct
{
    int		change;			/* variable has been changed	*/
    struct node	*tree;			/* parse tree to execute	*/
    Program	*graph;			/* pre-constructed `tree'	*/
} _background;

static	_background	background;

/*************************************************************************/

/*
 * Top level initialization of the background process by the executive.
 */

Error _dxf_ExInitBackground (void)
{
    int		size;

    size = sizeof (_background);

    memset (&background, NULL, size);

    return (OK);
}


/*
 * Cleanup function.
 */

void _dxf_ExCleanupBackground (void)
{
}


/*
 * Main loop interface to see whether any background jobs need to be done.
 */

int _dxf_ExCheckBackground (EXDictionary dict, int multiProc)
{
    Program		*graph;

    if (background.tree == NULL)
	return (FALSE);
    
    if (background.graph == NULL &&
	background.change && 
	(multiProc || _dxf_ExGQAllDone())) {
	_dxf_ExGraphInit ();
	graph = _dxf_ExGraph (background.tree);
	if (graph)
	    graph->origin = GO_BACKGROUND;
	else
	    background.change = FALSE;
	background.graph = graph;
	ExDebug ("1", "Creating graph %x for background", graph);
    }


    if (background.graph && _dxf_ExGQAllDone())
    {
        /* we are the master, send a copy of the parse tree
         * to all slaves
         */
        _dxf_ExSendParseTree(background.tree);
	_dxf_ExGQEnqueue (background.graph);
	ExDebug ("1", "Enqueuing graph %x for background", background.graph);
	background.graph = NULL;
	background.change = FALSE;
	return (TRUE);
    }
    else 
	return (FALSE);
}


/*
 * Called whenever a variable changes in the global dictionary.
 */

void _dxf_ExBackgroundChange (void)
{
    _dxf_ExVCRChange();

    if (background.tree == NULL)
	return;

    background.change = TRUE;
}

void _dxf_ExBackgroundChangeReset (void)
{
    _dxf_ExVCRChangeReset();

    if (background.tree == NULL)
	return;

    background.change = FALSE;
}

/*
 * Called whenever a macro is redefined.
 */
void _dxf_ExBackgroundRedo (void)
{
    _dxf_ExVCRRedo();

    if (! background.tree)
	return;

    if (background.graph != NULL)
    {
	_dxf_ExGraphDelete(background.graph);
	background.graph = NULL;
    }

    background.change = TRUE;
}



/*
 * The background command processor.  Used to set up or cancel the
 * background graph.
 */

void _dxf_ExBackgroundCommand (_bg comm, struct node * n)
{
    struct node		*old = NULL;

    switch (comm)
    {
	case BG_STATEMENT:
            /* do not automatically execute graph once when put */
            /* in background mode, UI will take care of first execution */
	    background.change = FALSE;
	    old = background.tree; 
	    background.tree = n;
	    break;

	case BG_CANCEL:
	    background.change = FALSE;
	    old = background.tree; 
	    background.tree = NULL;
	    break;
	
	default:
	    DXWarning ("#4590", "Background", comm);
	    break;
    }
    if (background.graph)
	_dxf_ExGraphDelete(background.graph);
    background.graph = NULL;

    if (old)
	_dxf_ExPDestroyNode (old);
}
