/*
 *  ratlib.h
 *  Rat
 *
 *  Created by Curtis Jones on 2009.11.15.
 *  Copyright 2009 __MyCompanyName__. All rights reserved.
 *
 */

#ifndef __RATLIB_H__
#define __RATLIB_H__

#include "/usr/include/semaphore.h"

struct opool;
struct ratlibgrid;
struct ratlibimage;
struct ratlibpoint;

//
// memlock
//
struct memlock
{
	int32_t volatile inuse;						// current reference count
	int (*destroy)(void*);						// destroy function pointer
	void *object;											// context object
	struct memlock *next;							// memlock release list
};
typedef struct memlock memlock_t;

//
// memlock_destroy_func
//
typedef int (*memlock_destroy_func)(void*);

/**
 *
 */
int memlock_setup ();

/**
 *
 */
int memlock_init (memlock_t*, memlock_destroy_func, void*);

/**
 *
 */
int memlock_destroy (memlock_t*);

/**
 *
 */
void memlock_retain (memlock_t*);

/**
 *
 */
void memlock_release (memlock_t*);





//
// cobject
//
struct cobject
{
	memlock_t memlock;								// reference counting mechanism
	struct opool *pool;								// object pool
};
typedef struct cobject cobject_t;

//
// cobject_destroy_func
//
typedef int (*cobject_destroy_func)(cobject_t*);

/**
 * cobject, destroy function pointer, object pool (optional)
 */
int cobject_init (cobject_t*, cobject_destroy_func, struct opool*);

/**
 *
 */
int cobject_destroy (cobject_t*);

/**
 *
 */
cobject_t* cobject_retain (cobject_t*);

/**
 *
 */
void cobject_release (cobject_t*);





//
// semaphore
//
struct semaphore
{
	cobject_t cobject;								// super class
	
	sem_t *sem;												// semaphore
	char name[20];										// semaphore name
};
typedef struct semaphore ratlibsem_t;

/**
 *
 */
int semaphore_init (ratlibsem_t*, struct opool*);

/**
 *
 */
int semaphore_destroy (ratlibsem_t*);

/**
 *
 */
int semaphore_post (ratlibsem_t*);

/**
 *
 */
int semaphore_wait (ratlibsem_t*);

/**
 *
 */
ratlibsem_t* semaphore_retain (ratlibsem_t*);

/**
 *
 */
void semaphore_release (ratlibsem_t*);





//
// opool_item
//
struct opool_item
{
	struct opool_item *next;					// next opool item
};
typedef struct opool_item opool_item_t;

//
// opool_block
//
struct opool_block
{
	struct opool_block *next;					// next opool block
};
typedef struct opool_block opool_block_t;

//
// opool
//
struct opool
{
	cobject_t cobject;								// super class
	
	ratlibsem_t semaphore;						// semaphore
	
	char name[100];										// object pool name
	uint64_t osize;										// object size (in bytes)
	uint64_t bsize;										// block size (in objects)
	uint64_t bmax;										// max blocks
	
	uint64_t bcount;									// current number of allocated blocks
	uint64_t ocount;									// current number of allocated objects
	
	opool_block_t *blocks;						// list of opool blocks
	opool_item_t *items;							// list of opool items
	
	int (*init)(struct opool*,void*);
};
typedef struct opool opool_t;

//
// opool_object_init_func
//
typedef int (*opool_object_init_func) (opool_t*, void*);

/**
 * opool, object size, block size (in objects), max blocks, pool name
 */
int opool_init (opool_t*, uint64_t, uint64_t, uint64_t, char*);

/**
 * opool, object size, block size (in objects), max blocks, pool 
 * name, object init function pointer
 */
int opool_init2 (opool_t*, uint64_t, uint64_t, uint64_t, char*, opool_object_init_func);

/**
 * opool
 */
int opool_destroy (opool_t*);

/**
 *
 */
int opool_push (opool_t*, void*);

/**
 *
 */
int opool_pop (opool_t*, void**);

/**
 *
 */
opool_t* opool_retain (opool_t*);

/**
 *
 */
void opool_release (opool_t*);





//
// thread_state
//
typedef enum
{
	THREAD_STATE_ERROR   = -1,
	THREAD_STATE_STARTED = (1<<0),
	THREAD_STATE_STOPPED = (1<<1),
	THREAD_STATE_STOPPING = (1<<2)
} thread_state;

//
// thread
//
struct thread
{
	cobject_t cobject;								// super class
	
	pthread_t pthread;								// posix thread
	thread_state state;								// state
	
	void *(*start_func)(void*);				// start func
	void *arg;												// arg
};
typedef struct thread ratlibthread_t;

//
// thread_start_func
//
typedef void * (*thread_start_func) (void *);

/**
 *
 */
int thread_init (ratlibthread_t*, thread_start_func, void*restrict, opool_t*);

/**
 *
 */
int thread_destroy (ratlibthread_t*);

/**
 *
 */
int thread_start (ratlibthread_t*);

/**
 *
 */
int thread_stop (ratlibthread_t*);

/**
 *
 */
thread_state thread_getstate (ratlibthread_t*);

/**
 *
 */
int thread_signal (ratlibthread_t*, int);

/**
 *
 */
ratlibthread_t* thread_retain (ratlibthread_t*);

/**
 *
 */
void thread_release (ratlibthread_t*);





//
// ratlibpoint
//
struct ratlibpoint
{
	cobject_t cobject;								// super class
	struct ratlibpoint *prev;					// parent point
	uint32_t x;												// horizontal axis
	uint32_t y;												// vertical axis
};
typedef struct ratlibpoint ratlibpoint_t;

/**
 *
 */
int ratlibpoint_init (ratlibpoint_t*, opool_t*);

/**
 * point, pool, x (horizontal axis), y (vertical axis)
 */
int ratlibpoint_init2 (ratlibpoint_t*, opool_t*, uint32_t, uint32_t);

/**
 *
 */
int ratlibpoint_destroy (ratlibpoint_t*);

/**
 *
 */
int ratlibpoint_equals (ratlibpoint_t*, ratlibpoint_t*);

/**
 *
 */
int ratlibpoint_setprev (ratlibpoint_t*, ratlibpoint_t*);

/**
 *
 */
ratlibpoint_t* ratlibpoint_retain (ratlibpoint_t*);

/**
 *
 */
void ratlibpoint_release (ratlibpoint_t*);





#define RATLIB_IMAGE_OPTION_ALPHA_FIRST (1<<0)
#define RATLIB_IMAGE_OPTION_ALPHA_LAST  (1<<1)

//
// pixel
//
struct pixel
{
	uint8_t r;												// red
	uint8_t g;												// green
	uint8_t b;												// blue
	uint8_t a;												// alpha
};
typedef struct pixel pixel_t;

//
// ratlibimage
//
struct ratlibimage
{
	cobject_t cobject;								// super class
	
	pixel_t *data;										// 
	uint32_t size;										// size of data (in bytes)
	
	uint32_t width;										// image width (in pixels)
	uint32_t height;									// image height (in pixels)
};
typedef struct ratlibimage ratlibimage_t;

/**
 * ratlibimage, pool, data, options, bytes per pixel, width, height
 */
int ratlibimage_init (ratlibimage_t*, opool_t*, uint8_t*, uint32_t, uint32_t, uint32_t, uint32_t);

/**
 *
 */
int ratlibimage_destroy (ratlibimage_t*);

/**
 *
 */
pixel_t* ratlibimage_pixelatpoint (ratlibimage_t*, ratlibpoint_t*);

/**
 *
 */
ratlibimage_t* ratlibimage_retain (ratlibimage_t*);

/**
 *
 */
void ratlibimage_release (ratlibimage_t*);

/**
 *
 */
int pixel_equals (pixel_t*, pixel_t*);

/**
 *
 */
int pixel_similar (pixel_t*, pixel_t*);





//
// slist_item
//
struct slist_item
{
	struct slist_item *next;					// next item
	void *data;												// 
};
typedef struct slist_item slist_item_t;

//
// slist
//
struct slist
{
	slist_item_t *head;								// head of the list
	uint32_t count;										// item count
	opool_t *pool;										// slist_item_t pool
};
typedef struct slist slist_t;

//
// slist_iter
//
struct slist_iter
{
	slist_item_t *item;								// 
};
typedef struct slist_iter slist_iter_t;

/**
 * list, pool (slist_item_t)
 */
int slist_init (slist_t*, opool_t*);

/**
 *
 */
int slist_destroy (slist_t*);

/**
 *
 */
int slist_push (slist_t*, cobject_t*);

/**
 *
 */
int slist_pop (slist_t*, cobject_t**);

/**
 *
 */
int slist_iter_init (slist_t*, slist_iter_t*);

/**
 *
 */
int slist_iter_next (slist_iter_t*, cobject_t**);





#define RATLIB_GRID_VISITED (1<<0)
#define RATLIB_GRID_SET1    (1<<1)
#define RATLIB_GRID_SET2    (1<<2)
#define RATLIB_GRID_SET3    (1<<3)

//
// ratlibgrid
//
struct ratlibgrid
{
	cobject_t cobject;								// super class
	
	uint8_t *grid;										// grid data
	uint32_t width;										// grid width
	uint32_t height;									// grid height;
	
	slist_t set1;											// set1
	slist_t set2;											// set2
	slist_t set3;											// set3
};
typedef struct ratlibgrid ratlibgrid_t;

/**
 * ratlibgrid, pool, width, height
 */
int ratlibgrid_init (ratlibgrid_t*, opool_t*, uint32_t, uint32_t);

/**
 *
 */
int ratlibgrid_destroy (ratlibgrid_t*);

/**
 *
 */
int ratlibgrid_isvisited (ratlibgrid_t*, ratlibpoint_t*);

/**
 *
 */
int ratlibgrid_markasvisited (ratlibgrid_t*, ratlibpoint_t*);

/**
 * grid, set
 */
int ratlibgrid_set_clear (ratlibgrid_t*, uint32_t);

/**
 * grid, set, point
 */
int ratlibgrid_set_mark (ratlibgrid_t*, uint32_t, ratlibpoint_t*);

/**
 * grid, set, point
 */
int ratlibgrid_set_unmark (ratlibgrid_t*, uint32_t, ratlibpoint_t*);

/**
 * grid, set, point
 */
int ratlibgrid_set_marked (ratlibgrid_t*, uint32_t, ratlibpoint_t*);

/**
 * grid, set, point (return value)
 */
int ratlibgrid_set_any (ratlibgrid_t*, uint32_t, ratlibpoint_t**);

/**
 * grid, set
 */
int ratlibgrid_set_count (ratlibgrid_t*, uint32_t);

/**
 * grid, point, set source, set destination
 */
int ratlibgrid_set_aups (ratlibgrid_t*, ratlibpoint_t*, uint32_t, uint32_t);

/**
 * grid, point, set source, set destination
 */
int ratlibgrid_set_amps (ratlibgrid_t*, ratlibpoint_t*, uint32_t, uint32_t);

/**
 *
 */
ratlibgrid_t* ratlibgrid_retain (ratlibgrid_t*);

/**
 *
 */
void ratlibgrid_release (ratlibgrid_t*);





//
// ratlibsession
//
struct ratlibsession
{
	cobject_t cobject;								// parent class
	ratlibgrid_t grid;								// 
	ratlibimage_t *image;							// 
	ratlibpoint_t *begpoint;					// begin point
	ratlibpoint_t *endpoint;					// end point
	ratlibpoint_t *solution;					// maze solution
};
typedef struct ratlibsession ratlibsession_t;

/**
 *
 */
int ratlibsession_init (ratlibsession_t*, opool_t*, ratlibimage_t*);

/**
 *
 */
int ratlibsession_destroy (ratlibsession_t*);

/**
 *
 */
int ratlibsession_setbeg (ratlibsession_t*, ratlibpoint_t*);

/**
 *
 */
int ratlibsession_setend (ratlibsession_t*, ratlibpoint_t*);

/**
 *
 */
int ratlibsession_setsolution (ratlibsession_t*, ratlibpoint_t*);

/**
 *
 */
int ratlibsession_solve (ratlibsession_t*);

/**
 *
 */
ratlibsession_t* ratlibsession_retain (ratlibsession_t*);

/**
 *
 */
void ratlibsession_release (ratlibsession_t*);





//
// ratlibpools
//
struct ratlibpools
{
	opool_t ratlibimage;							// ratlibimage_t
	opool_t ratlibpoint;							// ratlibpoint_t
	opool_t ratlibsession;						// ratlibsession_t
	opool_t slist_item;								// slist_item_t
};
typedef struct ratlibpools ratlibpools_t;

//
// ratlib
//
struct ratlib
{
	ratlibpools_t pools;							// core pools
};
typedef struct ratlib ratlib_t;

/**
 *
 */
int ratlib_init ();

/**
 *
 */
int ratlib_destroy ();

/**
 *
 */
ratlibpools_t* ratlib_pools ();

/**
 *
 */
ratlibsession_t* ratlib_session (ratlibimage_t*);

/**
 * x (horizontal), y (vertical)
 */
ratlibpoint_t* ratlib_point (uint32_t, uint32_t);

/**
 * data, options, bytes per pixel, width, height
 */
ratlibimage_t* ratlib_image (const uint8_t*, uint32_t, uint32_t, uint32_t, uint32_t);

/**
 *
 */
void ratlib_memstats ();

/**
 *
 */
void ratlib_memstats_pool (opool_t*);





// because these probably aren't already defined a dozen
// times elsewhere.
#ifndef MAX
#define MAX(a,b) ((a)>(b)?(a):(b))
#endif

#ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
#endif

// used to give gcc hints regarding branch prediction
#define likely(x) __builtin_expect((x),1)
#define unlikely(x) __builtin_expect((x),0)

#ifdef LOG_LEVEL

//
// error
//
#if LOG_LEVEL >= 1
#define LOG1(...) printf(__VA_ARGS__)
#else
#define LOG1(...)
#endif

//
// ?
//
#if LOG_LEVEL >= 2
#define LOG2(...) printf(__VA_ARGS__)
#else
#define LOG2(...)
#endif

//
// standard
//
#if LOG_LEVEL >= 3
#define LOG3(...) printf(__VA_ARGS__)
#else
#define LOG3(...)
#endif

//
// ?
//
#if LOG_LEVEL >= 4
#define LOG4(...) printf(__VA_ARGS__)
#else
#define LOG4(...)
#endif

//
// debug
//
#if LOG_LEVEL >= 5
#define LOG5(...) printf(__VA_ARGS__)
#else
#define LOG5(...)
#endif

#else

#define LOG1(...)
#define LOG2(...)
#define LOG3(...)
#define LOG4(...)
#define LOG5(...)

#endif

#define LOG_ERROR_AND_BREAK(...) {LOG5(__VA_ARGS__); break;}
#define LOG_ERROR_AND_CONTINUE(...) {LOG5(__VA_ARGS__); continue;}
#define LOG_ERROR_AND_GOTO(a,b,...) {LOG5(__VA_ARGS__); error=a; goto b;}
#define LOG_ERROR_AND_RETURN(a,...) {LOG5(__VA_ARGS__); return a;}

#endif /* __RATLIB_H__ */
