#include "Scian.h"
#include "ScianIDs.h"
#ifdef GRAPHICS
Cant do that, bucko!
#endif
#include "ScianTypes.h"
#include "ScianNames.h"
#include "ScianArrays.h"
#include "ScianLists.h"
#include "ScianSockets.h"
#include "ScianLib.h"
#include "ScianWindows.h"
#include "ScianDatasets.h"
#include "ScianGarbageMan.h"
#include "ScianScripts.h"
#include "ScianNetObjects.h"

/* definitions stolen from ScianMain.c */
Bool runningRemote = false;
real missingData = 1.1E37;
real plusInf = 1E37;
real minusInf = -1E37;
Bool demoP = false;
Bool scriptSelectP = false;
Bool abortScriptP = true;

int LibRunning()
{
    return libRunning;
}

double MyClock()
{
    struct tms buffer;

    return times(&buffer) / HEARTBEAT;
}

#ifdef PROTO
void InitLib(char *name)
#else
void InitLib(name)
char *name;
#endif
{
    if (name && strncmp(name, "", 3))
    {
	whatsMyName = malloc(strlen(name) + 1);
	strcpy(whatsMyName, name);
    }

    libRunning = true;
    InitNames();
    InitObjects();
    InitArrays();
    InitLists();
#ifdef SOCKETS
    InitSockets();
#endif
    InitTimers();
    InitDatasets();
    DoEnablePublication();
}
void InitStuff()
{
    /* stub to replace ScianMain.c:InitStuff */
}

void KillLib()
{
    KillDatasets();
    KillTimers();
#ifdef SOCKETS
    KillSockets();
#endif
    KillLists();
    KillArrays();
    KillObjects();
    KillNames();
    libRunning = false;
}

void IdleLib()
{
#if 0
    IdleAllConnections();
    TrashDay();
#else
    LongIdleLib();
#endif
}

void LongIdleLib()
{
    int hak, idle;
    double lastTime;

    hak = 0;
    idle = false;

    lastTime = MyClock();

    while (!idle)
    {
	IdleAllConnections();
	if (++hak > 100)
	{
	    hak = 0;
	    TrashDay();
	}

	if (lastTime + 5.0 < MyClock())
	{
	    idle = AllConnectionsIdle(true);
	    lastTime = MyClock();
	}
	else
	{
	    idle = AllConnectionsIdle(false);
	}
    }
}

int AdvertiseInteger(theInt)
int theInt;
{
    ObjPtr theIntObj;

    if (!libRunning)
    {
	fprintf(stderr, "AdvertiseInteger: SciAn library not initialized\n");
	return;
    }

    theIntObj = NewInt(theInt);
    if (!theIntObj)
    {
	fprintf(stderr, "memory!\n");
	exit (-1);
    }

    if (AdvertiseObject(theIntObj))
    {
#if 0
	return GetInt(GetVar(theIntObj, NETWORKID));
#else
	return GetInt(GetVar(theIntObj, 998));
#endif
    }
    return 0;
}

#ifdef PROTO
int AdvertiseCArray(char *name, real *arr, int rank, ...)
#else
int AdvertiseCArray(name, arr, rank)
real *arr;
int rank;
char *name;
#endif
{
    long *dimPtr;
    ObjPtr dataForm, dimsArray, data, boundsArray, theDataset;
    real dims[23];
    real bounds[23 * 2];
    int i;

    if (!libRunning)
    {
	fprintf(stderr, "AdvertiseCArray: SciAn library not initialized\n");
	return 0;
    }

    if (rank < 2 || rank > 3)
    {
	fprintf(stderr, "rank smell!\n");
	return 0;
    }

    dataForm = NewObject(dataFormClass, 0);
    dimsArray = NewRealArray(1, (long) rank);
    if (!dataForm || !dimsArray)
    {
	fprintf(stderr, "memory!\n");
	exit (-1);
    }

    /*Put in some dimensions*/
    dimPtr = (long *) (&rank + 1);
    for (i = 0; i < rank; ++i)
    {
	/* is this paranoia or what? */
	dims[i] = (real) *(dimPtr++);
    }
    CArray2Array(dimsArray, dims);
    SetVar(dataForm, DIMENSIONS, dimsArray); 

    /*Put in the bounds*/
    for (i = 0; i < rank; ++i)
    {
	bounds[2 * i] = 0;
	bounds[2 * i + 1] = dims[i] - 1;
    }
    boundsArray = NewRealArray(1, (long) 2 * rank);
    if (!boundsArray)
    {
	fprintf(stderr, "memory!\n");
	exit (-1);
    }
    CArray2Array(boundsArray, bounds);
    SetVar(dataForm, BOUNDS, boundsArray);

    /* create the data array */
    switch(rank)
    {
	case 2:
	    data = NewRealArray(2, (long) dims[0], (long) dims[1]);
	    theDataset = NewObject(data2DScalar, 0);
	    break;
	case 3:
	    data = NewRealArray(3, (long) dims[0], (long) dims[1], (long) dims[2]);
	    theDataset = NewObject(data3DScalar, 0);
	    break;
    }
    if (!data || !theDataset)
    {
	fprintf(stderr, "memory!\n");
	exit (-1);
    }
    CArray2Array(data, arr);

    /*Create the field*/
    SetVar(theDataset, DATA, data);
    SetVar(theDataset, DATAFORM, dataForm);
    if (name && *name)
    {
	SetVar(theDataset, NAME, NewString(name));
    }
    else
    {
	SetVar(theDataset, NAME, NewString((rank == 3) ? "3-D Array" : "2-D Array"));
    }
    SetVar(theDataset, DIRECTORY, NewString("/scri4d/a/users/murray/sciancomp"));

    if(AdvertiseObject(theDataset))
    {
	return GetInt(GetVar(theDataset, NETWORKID));
    }
    return 0;
}


#ifdef PROTO
int UpdateCArray(int netid, real *arr, int rank, ...)
#else
int UpdateCArray(netid, arr, rank)
int netid;
real *arr;
int rank;
#endif
/* UpdateCArray replaces the old value of DATA with the new array. For this to
 * work properly, the new data array MUST be of the same shape as the old one.
 * ( but this is currently not checked)
 */
{
    ObjPtr theDataset;
    ObjPtr data;
    real dims[23];
    long *dimPtr;
    int i;

    if (!libRunning)
    {
	fprintf(stderr, "AdvertiseCArray: SciAn library not initialized\n");
	return 0;
    }

    theDataset = FindPublishedObject(netid);

    if (! theDataset)
    {
	return 0;
    }

    dimPtr = (long *) (&rank + 1);
    for (i = 0; i < rank; ++i)
    {
        /* is this paranoia or what? */
        dims[i] = (real) *(dimPtr++);
    }


    switch(rank)
    {
	case 2:
	    data = NewRealArray(2, (long) dims[0], (long) dims[1]);
	    break;
	case 3:
	    data = NewRealArray(3, (long) dims[0], (long) dims[1], (long) dims[2]);
	    break;
    }
    CArray2Array(data, arr);
    SetVar(theDataset, DATA, data);
    return 1;
}
