#include <epp_pal.h>
#include "swi-internals.h"

typedef enum {
    ENGINE_IDLE	= 0,	/* TSD values are NULL by default */
    ENGINE_BUSY = 1,
} engine_state_t;

#ifdef EPP_MULTIPLE_ENGINES
#include <pthread.h>

static pthread_key_t	engine_state_key;

__attribute__((__constructor__)) static int __swi_engines_init(void) {
    return(pthread_key_create(&engine_state_key, NULL));
}

__attribute__((__destructor__)) static void __swi_engines_shutdown(void) {
    pthread_key_delete(engine_state_key);
}

void __swi_set_engine_idle(void) {
     pthread_setspecific(engine_state_key, (void*)ENGINE_IDLE);
}

void __swi_set_engine_busy(void) {
     pthread_setspecific(engine_state_key, (void*)ENGINE_BUSY);
}

static int __swi_is_engine_busy(void) {
    return(pthread_getspecific(engine_state_key) == (void*)ENGINE_BUSY);
}
#else /* EPP_MULTIPLE_ENGINES */
static engine_state_t	engine_state;

__attribute__((__constructor__)) static int __swi_engines_init(void) {
    engine_state = ENGINE_IDLE;
    return(0);
}

void __swi_set_engine_idle(void) {
    engine_state = ENGINE_IDLE;
}

void __swi_set_engine_busy(void) {
    engine_state = ENGINE_BUSY;
}

static int __swi_is_engine_busy(void) {
    return(engine_state == ENGINE_BUSY);
}
#endif /* EPP_MULTIPLE_ENGINES */

int pl_attach_engine(void) {
    return (PL_thread_attach_engine(NULL) >= 0 ? PL_TRUE : PL_ERROR_PAL);
}

int pl_detach_engine(void) {
    return(PL_thread_destroy_engine());
}

int pl_is_engine_attached(void) {
    int r = PL_thread_self();
    return((r >= 0 || r == -2) ? PL_TRUE : PL_FALSE);
}

int pl_is_engine_idle(void) {
    int r;
    
    if (__swi_is_engine_busy())
	return(PL_FALSE);
    
    r = PL_thread_self();
    if (r >= 0) {
	return(PL_set_engine(PL_ENGINE_CURRENT, NULL) == PL_ENGINE_SET ? PL_TRUE : PL_FALSE);
    } else if (r == -2) {
	return(PL_set_engine(PL_ENGINE_MAIN, NULL) == PL_ENGINE_SET ? PL_TRUE : PL_FALSE);
    }

    return(PL_ERROR_PAL);
}
