/* 
 *Database Connect Base Driver Object
 *
 * Author  : Johnathan Ingram
 * Date    : 31 August 1999
 * Updated :
 *   Version 0.2.0 : 16 July 2001, Johnathan Ingram
 */

#ifndef _dbconnBASEDriver
#define _dbconnBASEDriver

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <vector>


#define F_NAME_SIZE        256
#define MAX_ERRMSG_SIZE    4096
#ifdef WIN32
    //Shitty Visual C++ does not support long long
	#define D_LONG  long
	#define D_ULONG unsigned long
#else
	#define D_LONG  long long
	#define D_ULONG unsigned long long
#endif




// ----------------------------------------------------------
// BASE_DBBindParameter object 
// ----------------------------------------------------------
class BASE_DBBindParameter
{
	public:	
		//Public Vars
		char  *bname;    //Name of the field to bind OR
		int    bpos;     //Position of the field to bind.

		void   *valptr;  //Pointer to the bind variable.
		int    valsize;  //Size of the variable.

		BASE_DBBindParameter();
		virtual ~BASE_DBBindParameter();

		virtual void asString(void *bvar, unsigned long bvarsize) = 0;
		virtual void asInteger(void *bvar, unsigned long bvarsize) = 0;
		virtual void asUInteger(void *bvar, unsigned long bvarsize) = 0;
		virtual void asFloat(void *bvar, unsigned long bvarsize) = 0;
		virtual void asDateTime(void *bvar, unsigned long bvarsize) = 0;
		virtual void asBoolean(void *bvar, unsigned long bvarsize) = 0;
		virtual void asBinary(void *bvar, unsigned long bvarsize) = 0;
};



// ----------------------------------------------------------
// BASE_DBField object 
// ----------------------------------------------------------
enum DBFieldType 
{
	FT_NULL,

	FT_BIT, 
	FT_CHAR,
	FT_STRING,
	FT_WSTRING,            //Wide String for unicode.
	FT_BLOB,
	FT_TIMESTAMP,
	FT_DATE,
	FT_TIME,
	FT_DATETIME,
	FT_FLOAT,
	FT_DOUBLE,
	FT_INTEGER,
	FT_SMALLINT,
	FT_WORD,
	FT_BOOLEAN
};


enum DBFieldTypeCategory 
{
	FTC_NORMAL,
	FTC_ARRAY	
};


class BASE_DBField
{	
	protected:
		D_LONG             _strtoll(const char *nptr, int base);
		D_ULONG            _strtoull(const char *nptr, int base);
		long double        _strtold(const char *nptr, int base);

	public:
		struct data_values   
		{
			unsigned long int  dataSize;         //Current data size of the data in the array.
			void               *data;            //Pointer to the current data in the array.
		};

		//Field Definition
		char                fieldName[F_NAME_SIZE];
		long int            fieldNum;
		DBFieldType         fieldType;
		DBFieldTypeCategory fieldTypeCat;
		
		bool                isIncrement;
		bool                isPriKey;
		bool                isUnique;
		bool                isNotNull;
		long int            precision;
		long int            scale;

		//Defines the current data for the current row.
		bool                     isNULL;          //Has no value assigned to the field.

		int                      val_index;       //Current index of value into the vector. (Zero based)
		std::vector<data_values> values;          //Vector that can store an array of values for this field.
		std::vector<int>         arr_dimensions;  //If we have array data this will store the dimensions.

		void                     *convertedData;  //Used for storing conversions.	
		void                     *extraInfo;      //Extra information attached to this field object.

		//TODO: Operator Overloading
		//BASE_DBField & operator[](int index);   
	
		//Constructor / Destructor
		BASE_DBField();
		virtual ~BASE_DBField();

		//Conversion functions
		//Had to implement methods and not make them abstract so that SWIG mappings would compile.
		virtual char*              asString() {return NULL;};
		virtual D_LONG             asInteger() {return 0;};
		virtual D_ULONG            asUInteger() {return 0;};
		virtual double             asFloat() {return 0;};
		virtual time_t             asDateTime() {return 0;};
		virtual bool               asBoolean() {return false;};
		virtual void*              asBinary() {return NULL;};
	
		void freeInternalValues();               //Should not be called by general population.
};


// ----------------------------------------------------------
// BASE_Driver object
// ----------------------------------------------------------

class BASE_Driver
{
	public:
		// Global Error Message Constants 
		enum DBCON_error_codes 
		{
			DBCON_ERROR_CONNECTING, 
			DBCON_ALREADY_CONNECTED, 
			DBCON_ERROR_DISCONNECTING,
			DBCON_NOT_CONNECTED,
			DBCON_QUERY_ERROR,
			DBCON_FIELD_OUT_OF_RANGE,
			DBCON_DATA_RETRIEVAL_ERROR,
			DBCON_NO_DATA,
			DBCON_EOF_REACHED,
			DBCON_BOF_REACHED,
			DBCON_INVALID_CONVERSION,
			DBCON_TRANSACTION_ALREADY_ACTIVE,
			DBCON_TRANSACTION_NOT_ACTIVE,
			DBCON_TRANSACTION_ERROR,
			DBCON_NOT_AN_ARRAY_ERROR,
			DBCON_ARRAY_INDEX_OUT_OF_RANGE_ERROR
		};

		int     errorCode;                    //Error code.
		char    errorMsg[MAX_ERRMSG_SIZE];    //Max size of MAX_ERRMSG_SIZE
		time_t  lastQueryTime;                //Last datetime a query was executed. 0 for never.

		//Dynamic array of fields
		BASE_DBField *fields;

		//Monitoring Flags
		bool               isConnected;
		bool               isBOF;
		bool               isEOF;
		bool               isTransaction;
		bool               errorSet;
		long int           recordNum;    //Current record number.
		long int           recordCount;  //Used for SELECT type statments.
		long int           affectedRows; //Used for INSERT UPDATE type statements.
		long int           lastIdentity; //Used to store the last ID value.
		long int           fieldCount;   //Number of fields in the result set.

		//Constructor / Destructor
		BASE_Driver();
		virtual ~BASE_Driver();

		virtual void setError(int globalErrCode, char *info) = 0;
		void clearError();
		char* getErrorMsg(int globalErrCode);

		virtual void connect(char *host, char *db_name, char *user, char *password) = 0;
		virtual void disconnect() = 0;

		virtual void clearBindParams() = 0;
		virtual BASE_DBBindParameter* bindParam(char *bname) = 0;
		virtual BASE_DBBindParameter* bindParam(int bpos) = 0;
		virtual void execute(char *query) = 0; 	

		virtual void first() = 0;
		virtual void last() = 0;
		virtual void next() = 0;
		virtual void prev() = 0;
    
		virtual char* field(unsigned int fieldnum) = 0;

		virtual void transBegin() = 0;
		virtual void transCommit() = 0;
		virtual void transRollback() = 0;
};

#endif
