/*
 * callback.c Copyright 1999 Christopher M Sedore. All Rights Reserved.
 * Please see the "COPYING" file for license details.
 * 
 * Simple routines to provide scheduled callbacks at specified intervals.
 */

#include "main.h"

TAILQ_HEAD(cbhead,timerentry) callbackHead;

struct timerentry {
	void (*callback)(void *);
	void *param;
	int fireTime;
	int interval;
	int recur;
	TAILQ_ENTRY(timerentry) list;
};

time_t curtime;

volatile int timerCallback=0;

int 
InsertEvent(struct timerentry *t) {
	struct timerentry *l;

  t->fireTime=curtime+t->interval;

  for (l=TAILQ_FIRST(&callbackHead);l;l=TAILQ_NEXT(l,list)) {
	if (l->fireTime>t->fireTime) {
		TAILQ_INSERT_BEFORE(l,t,list);
	 	break;
	}
  }

  if (!l) {
	TAILQ_INSERT_TAIL(&callbackHead,t,list);
  }

}

int
ScheduleCallback(int seconds, int count, void (*callback)(void *),void *param)
{
  struct timerentry *t,*l;

  t=malloc(sizeof(struct timerentry));

  if (!t)
	return 0;

  t->interval=seconds;

  t->callback=callback;

  t->param=param;

  if (!count)
	count=1;

  t->recur=count;

  BlockTimer();

  InsertEvent(t);

  if (!timerCallback) 
	  UnblockTimer();

  return 1;

}

int 
TimerInterval() {
  struct timerentry *t,*l;


  time(&curtime);

  printf("timer %i\n",curtime);


  BlockTimer();

  for (l=TAILQ_FIRST(&callbackHead);l;l=t) {
	t=TAILQ_NEXT(l,list);

	if (l->fireTime<=curtime) {
		l->callback(l->param);
		l->recur--;
		TAILQ_REMOVE(&callbackHead,l,list);
 		if (l->recur) {
			InsertEvent(l);
		} else {
			free(l);
		}
	}
  }
	
  UnblockTimer();
}

int
TimerInit()
{
	TAILQ_INIT(&callbackHead);
}
