#include <xbase64/xbase64.h>
#include <xbsql.h>

class MaxXBase;
class MaxXBParams;

extern "C" {
	MaxXBase * bmx_xbase_init(void * handle, const char * dir);
	bool bmx_xbase_execCommand(MaxXBase * db, const char * statement);
	
	XBSQLQuery * bmx_xbase_openQuery(MaxXBase * db, const char * statement);
	bool bmx_xbase_executeQuery(XBSQLQuery * sql);
	int bmx_xbase_getNumFields(XBSQLQuery * sql);
	int bmx_xbase_getFieldType(XBSQLSelect * sql, int index);
	const char * bmx_xbase_getFieldName(XBSQLSelect * sql, int index);
	int bmx_xbase_getFieldLength(XBSQLSelect * sql, int index);
	const char * bmx_xbase_getFieldText(XBSQLSelect * sql, int row, int index);
	int bmx_xbase_getNumRows(XBSQLQuery * sql);
	void bmx_xbase_deleteStatement(XBSQLQuery * sql);

	const char * bmx_xbase_lastError(MaxXBase * db);
	
	MaxXBParams * bmx_xbase_initParams(int count);
	void bmx_xbase_paramSetInt(MaxXBParams * params, int index, int value);
	void bmx_xbase_paramSetDouble(MaxXBParams * params, int index, double value);
	void bmx_xbase_paramSetChar(MaxXBParams * params, int index, const char * value);
	void bmx_xbase_paramSetData(MaxXBParams * params, int index, void * value);
	bool bmx_xbase_execute(XBSQLQuery * sql, MaxXBParams * params);
	void bmx_xbase_deleteParams(MaxXBParams * params);
	
	XBSQLTableSet * bmx_xbase_getTableSet(MaxXBase * db);
	int bmx_xbase_getNumTables(XBSQLTableSet * tableSet);
	const char * bmx_xbase_getTableName(XBSQLTableSet * tableSet, int table);
	
	void bmx_xbase_close(MaxXBase * db);
}

/* CLASSES */

class MaxXBase
{
public:
	MaxXBase(void * handle, const char * dir);
	~MaxXBase();
	
	bool execCommand(const char * statement);
	XBSQLQuery * openQuery(const char * statement);
	const char * lastError();
	XBSQLTableSet * getTableSet();
	
private:
	void * maxHandle;
	XBaseSQL xbs;
};

MaxXBase::MaxXBase(void * handle, const char * dir)
	: maxHandle(handle), xbs(dir)
{
}

bool MaxXBase::execCommand(const char * statement) {
	return xbs.execCommand(statement);
}

XBSQLQuery * MaxXBase::openQuery(const char * statement) {
	bool parsed;
	return xbs.openQuery(statement, parsed);
}

const char * MaxXBase::lastError() {
	return xbs.lastError();
}

XBSQLTableSet * MaxXBase::getTableSet() {
	return xbs.getTableSet();
}

MaxXBase::~MaxXBase() {
//	delete xbs;
}



class MaxXBParams
{
public:
	MaxXBParams(int count);
	~MaxXBParams();

	void setInt(int index, int value);
	void setDouble(int index, double value);
	void setChar(int index, const char * value);
	void setData(int index, void * value);
	int getSize();
	XBSQLValue * getParams();
	
private:
	int size;
	XBSQLValue * values;
};

MaxXBParams::MaxXBParams(int count)
	: size(count)
{
	values = new XBSQLValue[count];
}

MaxXBParams::~MaxXBParams() {
	delete [] values;
}


void MaxXBParams::setInt(int index, int value) {
	values[index] = value;
}

void MaxXBParams::setDouble(int index, double value) {
	values[index] = value;
}

void MaxXBParams::setChar(int index, const char * value) {
	values[index] = value;
}

void MaxXBParams::setData(int index, void * value) {
	values[index] = value;
}

int MaxXBParams::getSize() {
	return size;
}

XBSQLValue * MaxXBParams::getParams() {
	return values;
}


/* FUNCTIONS */

MaxXBase * bmx_xbase_init(void * handle, const char * dir) {
	return new MaxXBase(handle, dir);
}

bool bmx_xbase_execCommand(MaxXBase * db, const char * statement) {
	return db->execCommand(statement);
}

const char * bmx_xbase_lastError(MaxXBase * db) {
	return db->lastError();
}

XBSQLQuery * bmx_xbase_openQuery(MaxXBase * db, const char * statement) {
	return db->openQuery(statement);
}

bool bmx_xbase_executeQuery(XBSQLQuery * sql) {
	return sql->execute(0,0);
}

int bmx_xbase_getNumFields(XBSQLQuery * sql) {
	return sql->getNumFields();
}

int bmx_xbase_getFieldType(XBSQLSelect * sql, int index) {
	return (int)sql->getFieldType(index);
}

const char * bmx_xbase_getFieldName(XBSQLSelect * sql, int index) {
	return sql->getFieldName(index);
}

int bmx_xbase_getFieldLength(XBSQLSelect * sql, int index) {
	return sql->getFieldLength(index);
}

const char * bmx_xbase_getFieldText(XBSQLSelect * sql, int row, int index) {
	return sql->getField(row, index).getText();
}

int bmx_xbase_getNumRows(XBSQLQuery * sql) {
	return sql->getNumRows();
}

void bmx_xbase_deleteStatement(XBSQLQuery * sql) {
	delete sql;
}


MaxXBParams * bmx_xbase_initParams(int count) {
	return new MaxXBParams(count);
}

void bmx_xbase_paramSetInt(MaxXBParams * params, int index, int value) {
	params->setInt(index, value);
}

void bmx_xbase_paramSetDouble(MaxXBParams * params, int index, double value) {
	params->setDouble(index, value);
}

void bmx_xbase_paramSetChar(MaxXBParams * params, int index, const char * value) {
	params->setChar(index, value);
}

void bmx_xbase_paramSetData(MaxXBParams * params, int index, void * value) {
	params->setData(index, value);
}

bool bmx_xbase_execute(XBSQLQuery * sql, MaxXBParams * params) {
	sql->execute(params->getSize(), params->getParams());
}

void bmx_xbase_deleteParams(MaxXBParams * params) {
	delete params;
}

XBSQLTableSet * bmx_xbase_getTableSet(MaxXBase * db) {
	return db->getTableSet();
}

int bmx_xbase_getNumTables(XBSQLTableSet * tableSet) {
	return tableSet->getNumTables();
}

const char * bmx_xbase_getTableName(XBSQLTableSet * tableSet, int table) {
	return tableSet->getTableName(table);
}

void bmx_xbase_close(MaxXBase * db) {
	delete db;
}

