#ifndef R2_CORE_TASK_H
#define R2_CORE_TASK_H

#ifdef __cplusplus
extern "C" {
#endif

typedef void (*RCoreTaskCallback)(void *user, char *out);

typedef enum r_core_task_mode_t {
	R_CORE_TASK_MODE_COOP, // Current cooperative model
	R_CORE_TASK_MODE_THREAD, // True threading with isolated core
	R_CORE_TASK_MODE_FORK // Process fork with IPC
} RCoreTaskMode;

typedef enum r_core_task_state_t {
	R_CORE_TASK_STATE_BEFORE_START,
	R_CORE_TASK_STATE_RUNNING,
	R_CORE_TASK_STATE_SLEEPING,
	R_CORE_TASK_STATE_DONE
} RTaskState;

typedef struct r_core_task_t {
	int id;
	RTaskState state;
	bool transient; // delete when finished
	bool dispatched;
	bool cmd_log;
	RCoreTaskMode mode;
	RThreadSemaphore *running_sem;
	void *user;
	RCore *core;
	RCons *cons; // owned child console for captured command output
	struct r_cmd_context_t *cur_context; // innermost command context running on this task
	// Thread/fork specific
	RThread *thread; // Thread handle (for thread mode)
	int pid; // Process ID (for fork mode)
	// Existing dispatch mechanism
	RThreadCond *dispatch_cond;
	RThreadLock *dispatch_lock;
	// Command and results
	char *cmd;
	char *res;
	RCoreTaskCallback cb;
} RCoreTask;


typedef struct r_core_tasks_t {
	int task_id_next;
	RList *tasks;
	RList *tasks_queue;
	struct r_core_task_t *main_task;
	RThreadLock *lock;
#if !HAVE_TH_LOCAL
	RList *task_threads; // (thread, task) bindings resolved by r_core_task_self
#endif
	struct r_core_task_t *foreground_task; // Current ^C target
	RCoreTaskMode default_mode; // Default execution mode
	int tasks_running;
	RCore *main_core; // Reference to main core
} RCoreTaskScheduler;

R_API void r_core_task_scheduler_init(RCoreTaskScheduler *tasks, RCore *core);
R_API void r_core_task_scheduler_fini(RCoreTaskScheduler *tasks);
R_API RCoreTask *r_core_task_get(RCoreTaskScheduler *scheduler, int id);
R_API int r_core_task_running_tasks_count(RCoreTaskScheduler *scheduler);
R_API const char *r_core_task_status(RCoreTask *task);
R_API RCoreTask *r_core_task_new(RCore *core, RCoreTaskMode mode, bool create_cons, const char *cmd, RCoreTaskCallback cb, void *user);
R_API void r_core_task_enqueue(RCoreTaskScheduler *scheduler, RCoreTask *task);
R_API int r_core_task_run_sync(RCoreTaskScheduler *scheduler, RCoreTask *task);
R_API void r_core_task_sync_begin(RCoreTaskScheduler *scheduler);
R_API void r_core_task_sync_end(RCoreTaskScheduler *scheduler);
R_API void r_core_task_yield(RCoreTaskScheduler *scheduler);
R_API void r_core_task_sleep_begin(RCoreTask *task);
R_API void r_core_task_sleep_end(RCoreTask *task);
R_API int r_core_task_del(RCoreTaskScheduler *scheduler, int id);
R_API void r_core_task_del_all_done(RCoreTaskScheduler *scheduler);
R_API RCoreTask *r_core_task_self(RCoreTaskScheduler *scheduler);
R_API bool r_core_task_ismain(RCoreTaskScheduler *scheduler);
R_API void r_core_task_join(RCoreTaskScheduler *scheduler, RCoreTask *current, int id);
R_API void r_core_task_set_foreground(RCoreTaskScheduler *scheduler, int task_id);
R_API RCoreTask *r_core_task_get_foreground(RCoreTaskScheduler *scheduler);
R_API void r_core_task_set_default_mode(RCoreTaskScheduler *scheduler, RCoreTaskMode mode);
R_API RCoreTaskMode r_core_task_get_default_mode(RCoreTaskScheduler *scheduler);
R_API int r_core_task_run(RCoreTaskScheduler *scheduler, RCoreTask *task, int mode);
R_API int r_core_task_run_threaded(RCoreTaskScheduler *scheduler, RCoreTask *task);
R_API int r_core_task_run_forked(RCoreTaskScheduler *scheduler, RCoreTask *task);
R_API void r_core_task_set_foreground(RCoreTaskScheduler *scheduler, int task_id);
R_API RCoreTask *r_core_task_get_foreground(RCoreTaskScheduler *scheduler);

R_API RCoreTask *r_core_task_submit(RCore *core, const char *cmd, RCoreTaskCallback cb, void *user, bool capture_cons, int mode);
R_API int r_core_task_id(const RCoreTask *t);
R_API bool r_core_task_wait(RCoreTask *t, ut64 timeout_ms);
R_API bool r_core_task_cancel(RCoreTask *t, bool hard);
R_API void r_core_task_cancel_all(RCore *core, bool hard);
R_API void r_core_task_free(RCoreTask *t);

#ifdef __cplusplus
}
#endif

#endif
