/*
 *  ratlib.c
 *  RatLib
 *
 *  Created by Curtis Jones on 2009.11.13.
 *  Copyright 2009 __MyCompanyName__. All rights reserved.
 *
 */

#include "ratlib.h"
#include "logger.h"
#include "opool.h"
#include "slist.h"
#include <stdlib.h>
#include <string.h>

static ratlib_t gRatlib;

/**
 *
 *
 */
int
ratlib_init ()
{
	int error;
	ratlib_t *ratlib = &gRatlib;
	ratlibpools_t *pools = &gRatlib.pools;
	
	memset(ratlib, 0, sizeof(ratlib_t));
	
	srandomdev();
	
	if (0 != (error = memlock_setup()))
		LOG_ERROR_AND_RETURN(-101, "%s.. failed to memlock_setup, 0x%08X [%d]\n", __PRETTY_FUNCTION__, error, error);
	
	if (0 != (error = opool_init(&pools->ratlibimage, sizeof(ratlibimage_t), 100, 1, "ratlibimage_t")))
		LOG_ERROR_AND_RETURN(-102, "%s.. failed to opool_init(ratlibimage_t), 0x%08X [%d]\n", __PRETTY_FUNCTION__, error, error);
	
	if (0 != (error = opool_init(&pools->ratlibpoint, sizeof(ratlibpoint_t), 10000, 100, "ratlibpoint_t")))
		LOG_ERROR_AND_RETURN(-104, "%s.. failed to opool_init(ratlibpoint_t), 0x%08X [%d]\n", __PRETTY_FUNCTION__, error, error);
	
	if (0 != (error = opool_init(&pools->ratlibsession, sizeof(ratlibsession_t), 100, 1, "ratlibsession_t")))
		LOG_ERROR_AND_RETURN(-105, "%s.. failed to opool_init(ratlibsession_t), 0x%08X [%d]\n", __PRETTY_FUNCTION__, error, error);
	
	if (0 != (error = opool_init(&pools->slist_item, sizeof(slist_item_t), 10000, 100, "slist_item_t")))
		LOG_ERROR_AND_RETURN(-106, "%s.. failed to opool_init(slist_item_t), 0x%08X [%d]\n", __PRETTY_FUNCTION__, error, error);
	
	return 0;
}

/**
 *
 *
 */
int
ratlib_destroy ()
{
	int error;
	ratlibpools_t *pools = &gRatlib.pools;
	
	if (0 != (error = opool_destroy(&pools->ratlibimage)))
		LOG_ERROR_AND_RETURN(-101, "%s.. failed to opool_destroy(ratlibimage), 0x%08X [%d]\n", __PRETTY_FUNCTION__, error, error);
	
	if (0 != (error = opool_destroy(&pools->ratlibpoint)))
		LOG_ERROR_AND_RETURN(-103, "%s.. failed to opool_destroy(ratlibpoint), 0x%08X [%d]\n", __PRETTY_FUNCTION__, error, error);
	
	if (0 != (error = opool_destroy(&pools->ratlibsession)))
		LOG_ERROR_AND_RETURN(-104, "%s.. failed to opool_destroy(ratlibsession), 0x%08X [%d]\n", __PRETTY_FUNCTION__, error, error);
	
	if (0 != (error = opool_destroy(&pools->slist_item)))
		LOG_ERROR_AND_RETURN(-105, "%s.. failed to opool_destroy(slist_item), 0x%08X [%d]\n", __PRETTY_FUNCTION__, error, error);
	
	return 0;
}

/**
 *
 *
 */
ratlibpools_t*
ratlib_pools ()
{
	return &gRatlib.pools;
}

/**
 *
 *
 */
inline ratlibsession_t*
ratlib_session (ratlibimage_t *image)
{
	int error;
	opool_t *pool = &gRatlib.pools.ratlibsession;
	ratlibsession_t *session = NULL;
	
	if (unlikely(0 != (error = opool_pop(pool, (void**)&session))))
		LOG_ERROR_AND_RETURN(NULL, "%s.. failed to opool_pop(ratlibsession_t), 0x%08X [%d]\n", __PRETTY_FUNCTION__, error, error);
	
	if (unlikely(0 != (error = ratlibsession_init(session, pool, image))))
		LOG_ERROR_AND_GOTO(-101, fail, "%s.. failed to ratlibsession_init, 0x%08X [%d]\n", __PRETTY_FUNCTION__, error, error);
	
	return session;
	
fail:
	opool_push(pool, session);
	return NULL;
}

/**
 *
 *
 */
inline ratlibpoint_t*
ratlib_point (uint32_t x, uint32_t y)
{
	int error;
	opool_t *pool = &gRatlib.pools.ratlibpoint;
	ratlibpoint_t *point = NULL;
	
	if (unlikely(0 != (error = opool_pop(pool, (void**)&point))))
		LOG_ERROR_AND_RETURN(NULL, "%s.. failed to opool_pop(ratlibpoint_t), 0x%08X [%d]\n", __PRETTY_FUNCTION__, error, error);
	
	if (unlikely(0 != (error = ratlibpoint_init2(point, pool, x, y))))
		LOG_ERROR_AND_GOTO(-101, fail, "%s.. failed to ratlibpoint_init2, 0x%08X [%d]\n", __PRETTY_FUNCTION__, error, error);
	
	return point;
	
fail:
	opool_push(pool, point);
	return NULL;
}

/**
 *
 *
 */
inline ratlibimage_t*
ratlib_image (const uint8_t *data, uint32_t options, uint32_t bpp, uint32_t width, uint32_t height)
{
	int error;
	opool_t *pool = &gRatlib.pools.ratlibimage;
	ratlibimage_t *image = NULL;
	
	if (unlikely(0 != (error = opool_pop(pool, (void**)&image))))
		LOG_ERROR_AND_RETURN(NULL, "%s.. failed to opool_pop(ratlibimage_t), 0x%08X [%d]\n", __PRETTY_FUNCTION__, error, error);
	
	if (unlikely(0 != (error = ratlibimage_init(image, pool, data, options, bpp, width, height))))
		LOG_ERROR_AND_GOTO(-101, fail, "%s.. failed to ratlibimage_init, 0x%08X [%d]\n", __PRETTY_FUNCTION__, error, error);
	
	return image;
	
fail:
	opool_push(pool, image);
	return NULL;
}

/**
 *
 *
 */
void
ratlib_memstats ()
{
	ratlibpools_t *pools = &gRatlib.pools;
	
	ratlib_memstats_pool(&pools->ratlibimage);
	ratlib_memstats_pool(&pools->ratlibpoint);
	ratlib_memstats_pool(&pools->ratlibsession);
	ratlib_memstats_pool(&pools->slist_item);
}

/**
 *
 *
 */
void
ratlib_memstats_pool (opool_t *pool)
{
	LOG3("%s.. [%s] inuse=%llu ocount=%llu bcount=%llu high=%llu\n", __PRETTY_FUNCTION__, pool->name, pool->inuse, pool->ocount, pool->bcount, pool->high);
}
