/* 
 * Scheduler - implements and manages coroutines
 */

#ifndef SCHEDULER_DEFINED
#define SCHEDULER_DEFINED 1

#include "Common.h"
#include "Coro.h"
#include "List.h"
#include "CStack.h"

#ifdef __cplusplus
extern "C" {
#endif

typedef void (SchedulerStartCallback)(void *);
typedef void (SchedulerUpdateCallback)(void *, int);

typedef struct
{
    unsigned int sleepMicroseconds;
    size_t coroCount; 
    Coro *mainCoro;
    Coro *currentCoro;
    List *pausedCoros;
    List *recycledCoros;
    size_t maxToRecycle;

    void *context;
    void (*start_func)(void *);
    void *state; // just here in case other implementations need it
    void *callbackContext;
    SchedulerUpdateCallback *updateCallback;
} Scheduler;

Scheduler *Scheduler_new(void *state);
void Scheduler_free(Scheduler *self);

Coro *Scheduler_mainCoro(Scheduler *self);
Coro *Scheduler_currentCoro(Scheduler *self);

void Scheduler_secondsInSleepPeriod_(Scheduler *self, float seconds);
float Scheduler_secondsInSleepPeriod(Scheduler *self);
void Scheduler_yieldSleep(Scheduler *self);

size_t Scheduler_coroCount(Scheduler *self);
unsigned int Scheduler_hasCoro_(Scheduler *self, Coro *coro);

Coro *Scheduler_newCoro(Scheduler *self);
//Coro *Scheduler_createCoro(Scheduler *self, void *aContext, void (*func)(void *));
void Scheduler_startCoro(Scheduler *self, Coro *coro, void *aContext, void (*func)(void *));

void Scheduler_yield(Scheduler *self);

// kill coro --------------------------------------------- 

void Scheduler_prepareToKillCoro_(Scheduler *self, Coro *coro);
void Scheduler_killCoro_(Scheduler *self, Coro *coro); /* private */

// pause/resume coro -------------------------------------

Coro *Scheduler_prepareToPauseCurrentCoro(Scheduler *self);
void Scheduler_prepareToPauseCoro_(Scheduler *self, Coro *coro);
void Scheduler_pauseCoro_(Scheduler *self, Coro *coro); /* private */
int Scheduler_hasPausedCoro_(Scheduler *self, Coro *coro);
void Scheduler_resumeCoro_(Scheduler *self, Coro *coro);
//void Scheduler_pause(Scheduler *self);
//void Scheduler_resume(Scheduler *self);
void Scheduler_scheduleNext_(Scheduler *self, Coro *coro);

// wait ---------------------------------------------------

double Scheduler_waitSeconds_(Scheduler *self, double seconds);

// callbacks ---------------------------------------------- 

void Scheduler_callbackContext_(Scheduler *self, void *context);
void Scheduler_updateCallback_(Scheduler *self, SchedulerUpdateCallback *func);
void Scheduler_sendUpdateCallback(Scheduler *self);
void Scheduler_incrementCoroCount(Scheduler *self);
void Scheduler_decrementCoroCount(Scheduler *self);

void Scheduler_show(Scheduler *self);

// enumeration 

typedef void (SchedulerDoCallback)(void *);

void Scheduler_do_(Scheduler *self, SchedulerDoCallback *func);
void Scheduler_doOnObjects_(Scheduler *self, SchedulerDoCallback *func);

void Scheduler_selfTest(Scheduler *self);

#ifdef __cplusplus
}
#endif
#endif
