#include "task-model.h"
#include <assert.h>
#include <stdio.h>

struct task_s {
  task_body_f body;
  int executed;
  int computed;
  int result;
  struct task_s *depends_of;
};

struct task_future_int_s *__task_create_future(struct task_s *);

struct task_future_int_s {
  struct task_s *task;
};

struct task_s *task_new(task_body_f body) {
  struct task_s *task = malloc(sizeof(*task));
  task->body = body;
  task->executed = 0;
  task->computed = 0;
  task->depends_of = task; /* i.e. not initalized.  */
  return task;
}

void task_destroy(struct task_s *task) {
  free(task);
}

void
task_set_dependency(struct task_s *src, struct task_s *dst) {
  assert (dst != NULL);
  dst->depends_of = src;
}


void
task_run(struct task_s *task) {
  assert (task->depends_of != task);
  /* Don't execute yet. */
  task->executed = 1;
}

int
task_get_result(struct task_s *task) {
  void *params;
  
  if (task->computed) {
    return task->result;
  }

  assert (task->executed);

  if (!task->depends_of) {
    params = NULL;
  } else {
    params = (void *) __task_create_future(task->depends_of);
  }
  
  task->result = task->body(params);

  task->computed = 1;

  return task->result;
}

struct task_future_int_s *__task_create_future(struct task_s *task) {
  struct task_future_int_s *future = malloc(sizeof(*future));

  future->task = task;
  
  return future;
}

int
task_get_future(struct task_future_int_s *future) {
  int result = task_get_result(future->task);

  free(future);
  return result;
}

