/* Version 0.0
** From "Wayne's Little DSA Library" (DSA == Data Structures and
** Algorithms) Feel free to change, modify, or burn these sources, but if
** you modify them please don't distribute your changes without a clear
** indication that you've done so.  If you think your change is spiffy,
** send it to me and maybe I'll include it in the next release.
**
** Wayne Hayes, wayne@csri.utoronto.ca (preffered), or wayne@csri.toronto.edu
*/


#include <assert.h>
#include <stdio.h>
#include "misc.h"
#include "event.h"
#include "heap.h"


Time _event_now;


static int CmpEvents(foint A, foint B)
{
    EventInfo *a = (EventInfo*)A.v, *b = (EventInfo*)B.v;

    /* We can't just return (a->time - b->time) because we must
    ** return an int.
    */
    if(a->time < b->time)
	return -1;
    else if(a->time == b->time)
	return 0;
    else
	return 1;
}

static HEAP *Heap;

int InitEventList(int n)
{
    Heap = HeapAlloc(n, CmpEvents);
    _event_now = 0.0;
    return 1;
}


EventInfo *InsertEvent(Event event, Time delta, Object object)
{
    EventInfo *p = Calloc(1,sizeof(EventInfo));
    p->time = _event_now + delta;
    p->event = event;
    p->object = object;
    assert(delta >= 0.0 && delta <= 10.0e10);

    if(HeapInsert(Heap, p).i == ABSTRACT_ERROR.i)
    {
	fprintf(stderr, "out of event heap space\n");
	exit(1);
    }
    else
	return p;
}


/* We return the event just processed; it is the responsibility of the
** CALLER to free the memory.  The easiest way to do this is to call
** this function as "free(NextEvent());".
*/
EventInfo *NextEvent(void)
{
    EventInfo *next;
    next = HeapNext(Heap).v;
    if((void*)next == ABSTRACT_ERROR.v)
    {
	fprintf(stderr, "Ran out of events!!!\n");
	exit(1);
    }

    _event_now = next->time;

    /* call the event function */
    next->event(next->object);
    return next;
}

#if 1
void HeapTypePrint(EventInfo *a)
{
    printf("%.4g ", a->time);
}
#endif
