# include "pantasks.h"

static struct timeval start;
void TimerMark ();
float TimerElapsed (int reset);

int CheckController () {

  char *p, *q;
  int i, Njobs, status, JobID;
  Job *job;
  IOBuffer buffer;

  /* get the list of completed jobs (exit / crash), update the job status */
  if (!CheckControllerStatus()) return (TRUE);

  /*** check EXIT jobs ***/
  InitIOBuffer (&buffer, 0x100);
  // TimerMark ();
  // status = ControllerCommand ("stop", CONTROLLER_PROMPT, &buffer); 
  // if (VerboseMode()) gprint (GP_ERR, "stop controller %f\n", TimerElapsed(TRUE));

  TimerMark ();
  FlushIOBuffer (&buffer);
  status = ControllerCommand ("jobstack exit", CONTROLLER_PROMPT, &buffer);
  if (VerboseMode()) gprint (GP_ERR, "check exit stack %f\n", TimerElapsed(TRUE));
  if (!status) goto escape;

  /** programming error **/
  p = memstr (buffer.buffer, "USAGE: jobstack", buffer.Nbuffer);
  if (p != NULL) goto escape;

  /** parse job list **/
  status = sscanf (buffer.buffer, "%*s %d", &Njobs);
  if (status != 1) goto escape;
  if (VerboseMode()) gprint (GP_ERR, "parse %d jobs on stack %f\n", Njobs, TimerElapsed(TRUE));

  p = buffer.buffer;
  for (i = 0; (i < Njobs) && !TestElapsedCheck(); i++) {
    q = strchr (p, '\n');
    if (q == NULL) {
      gprint (GP_ERR, "controller message error: incomplete job list\n");
      break;
    }
    p = q + 1;
    status = sscanf (p, "%d", &JobID);

    job = FindControllerJob (JobID);
    if (job == NULL) {
      gprint (GP_ERR, "misplaced job? %d not in EXIT job list\n", JobID);
      continue;
    }
    /* this checks the individual job status, grabs stdout/stderr */
    CheckControllerJob (job);
  }
  if (VerboseMode()) gprint (GP_ERR, "clear %d exit jobs %f\n", i, TimerElapsed(TRUE));

  if (TestElapsedCheck()) goto finish;
  /* this will prevent us from ever checking crashed jobs... */

  /*** check CRASH jobs ***/
  FlushIOBuffer (&buffer);
  status = ControllerCommand ("jobstack crash", CONTROLLER_PROMPT, &buffer);
  if (!status) goto escape;

  p = memstr (buffer.buffer, "USAGE: jobstack", buffer.Nbuffer);
  if (p != NULL) goto escape;

  /** parse job list **/
  status = sscanf (buffer.buffer, "%*s %d", &Njobs);
  if (status != 1) goto escape;
  if (VerboseMode()) gprint (GP_ERR, "check crash stack %f\n", TimerElapsed(TRUE)); 

  p = buffer.buffer;
  for (i = 0; (i < Njobs) && !TestElapsedCheck(); i++) {
    q = strchr (p, '\n');
    if (q == NULL) {
      gprint (GP_ERR, "controller message error: incomplete job list\n");
      break;
    }
    p = q + 1;
    
    status = sscanf (p, "%d", &JobID);
    job = FindControllerJob (JobID);
    if (job == NULL) {
      gprint (GP_ERR, "misplaced job? %d not in CRASH job list\n", JobID);
      continue;
    }
    /* this checks the individual job status, grabs stdout/stderr */
    CheckControllerJob (job);
  }
  if (VerboseMode()) gprint (GP_ERR, "clear %d crash jobs %f\n", i, TimerElapsed(TRUE)); 

 finish:
  FlushIOBuffer (&buffer);
  // status = ControllerCommand ("run", CONTROLLER_PROMPT, &buffer);
  FreeIOBuffer (&buffer);
  return (TRUE);

 escape:
  FlushIOBuffer (&buffer);
  // status = ControllerCommand ("run", CONTROLLER_PROMPT, &buffer); 
  FreeIOBuffer (&buffer);
  return (FALSE);
}

void TimerMark () {
    gettimeofday (&start, (void *) NULL);
}

float TimerElapsed (int reset) {

  float dtime;
  struct timeval stop;

  gettimeofday (&stop, (void *) NULL);
  dtime = DTIME (stop, start);
  if (reset) gettimeofday (&start, (void *) NULL);
  return (dtime);
}
