/* Copyright (c) 2000  Kevin Sullivan <nite@gis.net>
 *
 * Please refer to the COPYRIGHT file for more information.
 */

#include <signal.h>
#include <sys/time.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <ncurses.h>

#include "defines.h"
#include "colors.h"
#include "timer.h"
#include "winio.h"
#include "cmds.h"
#include "lists.h"

#ifdef MEMWATCH
  #include "memwatch.h"
#endif

/* a list of scheduled events. Each carries a time when it is supposed
   to be performed, then deleted. */
ntimer_t *timers;

/* do any time events that are due */
void tevent(void)
{
  time_t t = time(NULL);
  ntimer_t *cur;
  
  for (cur=timers;cur;)
  {
    if (cur->t <= t)
    {
      pfunc(cur);
      if (cur->recurring) {
	cur->t = t + cur->interval;
      } else {
        /* this is inelegant: after deleting the element, we have to
	   start from the beginning. But note that pfunc could have side
  	   effects, thus it may not in general work to save cur->next
	   before deleting cur.  */
        deltimer(cur);
        cur = timers;
        continue;
      }
    }
    cur = cur->next;
  }
}

/* print the current timers */
void timerlist(WINDOW *win)
{
  ntimer_t *cur;
  int i, t, min, sec;
  time_t ct = time(NULL);
  
  if (!timers) {
    wp(win, "No timers set\n");
    drw(win);
    return;
  }

  for (cur=timers,i=0;cur;cur=cur->next,i++)
  {
    t = cur->t-ct;
    min = t/60;
    sec = t%60;
    wp(win, ""BRIGHT(BLUE)"%i. (in %i:%02i", i+1, min, sec);
    if (cur->recurring) {
      t = cur->interval;
      min = t/60;
      sec = t%60;
      wp(win, ", repeats at interval %i:%02i", min, sec);
    }
    wp(win, "): "WHITE"%s\n", cur->desc);
  }
  
  drw(win);
}

/* perform the function scheduled in t. */
void pfunc(ntimer_t *t)
{
  t->callback(t->data);
}

/* add a timer to the list. Return pointer to element in timer
   list. Note that data must be allocated with alloc. The desc
   argument is duplicated. */
ntimer_t *addtimer(int sec, void callback(void *data), void *data, char *desc,
                   bool recurring)
{
  ntimer_t *cur;
  time_t t = time(NULL);
  
  /* create new timerlist entry */
  cur = (ntimer_t *)malloc(sizeof(ntimer_t));
  cur->t = t+sec;
  cur->interval = sec;
  cur->callback = callback;
  cur->data = data;
  cur->desc = strdup(desc);
  cur->recurring = recurring;
  cur->next = NULL;
  
  /* add it to the list */
  list_append(ntimer_t, timers, cur);
  
  return((void *)cur);
}

void deltimer(ntimer_t *t)
{
  ntimer_t *cur;
  
  if (!t)
    return;

  list_unlink_cond(ntimer_t, timers, cur, cur==(ntimer_t *)t);
  
  if (!cur)
    return;
  
  free(cur->data);
  free(cur->desc);
  free(cur);
}

/* Delete a timed event by index (starting at 0). Returns TRUE if
 * successful, FALSE if the index was out-of-bounds.
 */
bool deltimer_by_index(int index)
{
  ntimer_t *event;

  list_nth(event, timers, index);
  if (event) {
    deltimer(event);
    return TRUE;
  }
  else
    return FALSE;
}
