#ifndef TASK_H
#define TASK_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

#include <stdint.h>
#include <stdbool.h>

#include "bctypes.h"
#include "interface.h"

#define tasksize

struct TaskTree {
	//Type of the task
	uint8_t task_type;
	bool trash;
	// Refresh interval
	uint16_t refresh_min;
	uint16_t refresh_max;
	bool seconds;
	//Reverse ptr
	struct TaskTree *ptr;
	union {
// Constant node values {{{
		uint16_t stable[4];
		uint16_t unstable[4];
		struct {
			struct TaskTree *next;
			uint8_t w;
			uint16_t stable[2];
		} stablenode;
		struct {
			struct TaskTree *next;
			uint8_t w;
			uint16_t unstable[2];
		} unstablenode;
//}}}
//Pin IO {{{
		//Read pin
		uint16_t readd;
		uint16_t reada;
		struct {
			uint16_t pin;
			uint8_t pinmode;
		} pinmode;
		struct {
			//Pin to write
			uint16_t pin;
			//Value to write
			bool value;
		} writed;
		struct {
			//Pin to write
			uint16_t pin;
			//Value to write
			uint8_t value;
		} writea;
//}}}
//Interrupt {{{
		struct {
			//Pin
			uint16_t pin;
			//Interrupt mode
			enum InterruptMode mode;
			//Is the interrupt initialized
			bool initialized;
			//Triggered
			bool triggered;
			//Pin status
			bool status;
		} interrupt;
//}}}
//Repeat, delay and step {{{
		struct {
			//Pointer to the tree
			struct TaskTree *tree;
			//Pointer to the original tree
			struct TaskTree *oldtree;
			//Start time of the task
			uint32_t start;
			//Inner task is done
			bool done;
		} repeat;
		//Waiting time
		uint64_t delay;
		//Milliseconds since boot
		uint64_t until;
		struct {
			//Pointer to lhs
			struct TaskTree *lhs;
			//Pointer to function for the rhs
			uint16_t rhs;
			//Return size of rhs
			uint8_t w;
		} step;
		struct {
			//Pointer to lhs
			struct TaskTree *lhs;
			//Pointer to function for the rhs
			uint16_t rhs;
			//Return size of rhs
			uint8_t w;
		} steps;
		struct {
			//Pointer to lhs
			struct TaskTree *lhs;
			//Pointer to function for the rhs
			uint16_t rhs;
			//Return size of rhs
			uint8_t w;
		} stepu;
		struct {
			//Pointer to lhs
			struct TaskTree *lhs;
			//Pointer to rhs
			struct TaskTree *rhs;
			//Width of the rhs
			uint8_t w;
		} seqs;
		struct {
			//Pointer to lhs
			struct TaskTree *lhs;
			//Pointer to the rhs
			struct TaskTree *rhs;
			//Width of the rhs
			uint8_t w;
		} sequ;
//}}}
//Parallel {{{
		struct {
			//Pointer to lhs
			struct TaskTree *lhs;
			//Pointer to rhs
			struct TaskTree *rhs;
		} tand;
		struct {
			//Pointer to lhs
			struct TaskTree *lhs;
			//Pointer to rhs
			struct TaskTree *rhs;
		} tor;
//}}}
//Sds {{{
		//Pointer to the sds
		struct BCShareSpec *sdsget;
		struct {
			//Pointer to the sds
			struct BCShareSpec *sds;
			//Pointer to the data that we write
			struct TaskTree *data;
		} sdsset;
		struct {
			//Pointer to the function
			uint16_t fun;
			//Pointer to the context
			struct TaskTree *ctx;
			//Pointer to the actual sds
			struct BCShareSpec *sds;
		} sdsupd;
//}}}
//Rate limit {{{
		struct {
			//Last execution
			uint32_t last_execution;
			//The ratelimited task
			struct TaskTree *task;
			//Storage of intermediate results
			struct TaskTree *storage;
		} ratelimit;
//}}}
//Peripherals {{{
		//The void * are the device specific states
		void *dhttemp;
		void *dhthumid;
		void *ledmatrixclear;
		void *ledmatrixdisplay;
		struct {
			void *id;
			uint8_t intensity;
		} ledmatrixintensity;
		struct {
			void *id;
			uint8_t x;
			uint8_t y;
			bool s;
		} ledmatrixdot;
		void *abutton;
		void *bbutton;
		void *lightsensor;
		struct {
			float humid;
			float temp;
			void *sensor;
		} setenvironment;
		void *airqualitysensor;
		void *gesturesensor;
//}}}
//Events {{{
		struct {
			uint8_t event_type;
			uint8_t task_id;
			struct TaskTree *next;

		} event;
//}}}
	} data;
};

//* Completes a task, checks if the return value changed and possibly sends it
void task_complete(struct MTask *task, uint16_t *stack);
//* Removes a task, marks trash
void task_remove(struct MTask *, uint16_t *stack);
//* Prints a task for debugging purposes
void task_print(struct MTask *t, bool verbose);
//* Recursively prints a tasktree
void tasktree_print(struct TaskTree *tt, int indent);
//* Just prints single tasktree node
void tasktree_print_node(struct TaskTree *tt);
//* Clone a tasktree and give it the parent
struct TaskTree *tasktree_clone(struct TaskTree *tree, struct TaskTree *rptr);
//* Destroy the given task node
void destroy_task_node(struct TaskTree* tt, struct MTask *t);
//* Retrieve a share
struct BCShareSpec *sds_get(uint8_t id);
//* Retrieve a peripheral
void *peripheral_get(uint8_t id);
//* Initialise a new task
bool task_register(struct MTask *data);
//* Create task tree to store the last unstable result on the stack
struct TaskTree *create_result_task(uint16_t *sp, uint16_t *stack);
//* Update the value of an SDS
void sds_update(uint8_t taskid, uint8_t sdsid, String255 value);
//* Update a value of an sds from mTask
void sds_set_mtask(struct BCShareSpec *sds, uint16_t *stack);
//* Push the current value of a share on the stack
uint16_t *sds_get_mtask(struct BCShareSpec *sds, uint16_t *stack);

#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* !TASK_H */

