/* wait_cmd.c */

#include <sys/types.h>
#include <sys/time.h>
#include "db.h"
#include "externs.h"
#include "interface.h"

struct oq {
  time_t when;
  dbref who;
  char *comm;
  struct oq *next;
};

struct oq *cs =NULL;

void do_wait_command(dbref who, const char *what, int nos)
{
  time_t mytime;
  struct oq *cur;
  struct oq *cur2;
  mytime = time(NULL);
  mytime += nos;
  if(!cs || cs->when >= mytime) {
    cur = malloc(sizeof(*cur));
    cur->next = cs;
    cs = cur;
  } else {
    for(cur = cs; cur->next && (cur->next->when < mytime); cur = cur->next);
    cur2 = malloc(sizeof(*cur2));
    cur2->next = cur->next;
    cur->next = cur2;
    cur = cur2;
  }
  cur->who = who;
  cur->comm = alloc_string(what);
  cur->when = mytime;
}

static void freer(struct oq *what)
{
  if(what->comm) free(what->comm);
  free(what);
}

static int check_a_waits()
{
  struct oq *cur;
  
  if(!cs) {
    return 0;
  }
  if(cs->when > time(NULL)) {
    return 0;			/* nothing to do right now */
  }
  cur = cs;
  cs = cs->next;
  if(cur->comm)
    trigobj(cur->who, cur->comm, cur->who);
  freer(cur);
  return 1;
}

void do_halt(dbref player, const char *what)
{
  dbref victim;

  if((victim = match_controlled(player, what)) != NOTHING) {
    if(Typeof(victim) != TYPE_PLAYER &&
       Typeof(victim) != TYPE_THING) {
      notify(player, "Illegal object type.");
      return;
    }
    else {
      halt_long(victim);
      notify(player, "Halted.");
      }
  }
  return;
}

void halt_long(dbref obj)
{
  struct oq *x;
  struct oq *y;

  x = y = cs;
  while(x) {
    if(x->who == obj) {
      if(y != x) {
	y->next = x->next;
	freer(x);
	x = y->next;
      }
      else {
	cs = cs -> next;
	freer(x);
	x = y = cs;
      }
    }
    else {
      y = x;
      x = x -> next;
    }
  }
  return;
}

void wc_every_sec()
{
  while(check_a_waits());
}
  
void do_wait(dbref who, const char *when,const char *comm)
{
  if(when)
    while(*when == ' ') when++;
  if(!when || !*when || !number(when) || !comm || !*comm) {
    notify(who,"Usage: @wait <seconds>=<command>");
    return;
  }
  do_wait_command(who, comm, atoi(when));
  notify(who, "Queued.");
}

void do_ps(dbref player, const char *who)
{
  dbref who_d = 0;
  struct oq *d;
  int count = 0;

  if(!(*who))
    if(!Arch(player))
      who = NAME(player);
  if(*who)
    who_d = lookup_player(who);

  if(who_d && (who_d == NOTHING || !controls(player, who_d))) {
    notify(player,"Permission denied!");
    return;
  }

  sprintf(buf, "%7s  %-22s %-25s %-20s",
	  "Wait", "Command", "Source", "Owner");
  notify(player, buf);

  for(d = cs; d; d = d->next) {
    if((!who_d && controls(player, d->who)) || (OWNER(d->who) == who_d)) {
      char tmp3[25];
      char *tmp1;
      char *tmp2;
      int x1, x2;

      tmp1 = alloc_string(unparse_object(player, d->who));
      tmp2 = alloc_string(unparse_object(player, OWNER(d->who)));
      strncpy(tmp3, d->comm, 22);

      x1 = strlen(tmp1) - 25;
      x2 = strlen(tmp2) - 20;
      if(x1 < 0)
	x1 = 0;
      if(x2 < 0)
	x2 = 0;

      sprintf(buf,"%7d  %-22s %-25s %-20s", (int) (d-> when - time(NULL)),
	      tmp3, tmp1 + x1,  tmp2 + x2);
      notify(player, buf);
      free((void *) tmp1);
      free((void *) tmp2);
    }
    count++;
  }

  sprintf(buf, "%d total processes.", count);
  notify(player, buf);
}