#include <stdio.h>
#include <stddef.h>
#include "coroutine.h"
#include "generator.h"
#include "asleep.h"
#include "task.h"

#include <dirent.h> 
#include <string.h>
#include <stdlib.h>
#include <time.h>

#define DEMO_STACK_SIZE (8192*sizeof(void *))

Coroutine *cor_main;

typedef struct {
    intptr_t headroom;
    bool canstartcoroutine;
} TestResult;


void *stacktest(
    void *param
){
    TestResult *testresult = (TestResult *)param;
    if (Coroutine_CanStartCoroutine(DEMO_STACK_SIZE)){
        Coroutine *cor = Coroutine_New(DEMO_STACK_SIZE, stacktest);
        Coroutine_Delete(cor);
    }
    testresult->headroom = Coroutine_GetStackHeadroom();
    testresult->canstartcoroutine = Coroutine_CanStartCoroutine(DEMO_STACK_SIZE);

    return NULL;
}


int main(int argc, char *argv[]) {
    (void)argc;
    (void)argv;

    unsigned char *stack_now = (unsigned char *)&argc;

    printf("Various stack headrooms:\n");
    intptr_t limitnocoroutine;
    TestResult testresult;

    // what stack do we get with no stack limit set
    limitnocoroutine = Coroutine_GetStackHeadroom();
    Coroutine_Run(DEMO_STACK_SIZE, stacktest, &testresult, NULL);
    printf("No stack limit: %ld %ld %d\n", limitnocoroutine, testresult.headroom, testresult.canstartcoroutine);

    // what stack do we get with an undersize stack limit
    for (size_t stacksize = DEMO_STACK_SIZE/2; stacksize < DEMO_STACK_SIZE*4; stacksize += DEMO_STACK_SIZE/2){
        Coroutine_SetStackLimit(stack_now - stacksize);
        limitnocoroutine = Coroutine_GetStackHeadroom();
        Coroutine_Run(DEMO_STACK_SIZE, stacktest, &testresult, NULL);
        printf("Stack=%ld: %ld, %ld %d\n", stacksize, limitnocoroutine, testresult.headroom, testresult.canstartcoroutine);
    }
}
