#ifndef _ISQLQUERYAS_H_
#define _ISQLQUERYAS_H_



// {C350F251-9EEB-494f-8045-8AEFD7F0EF05}
static const GUID IID_ISQLiteServer = 
{ 0xc350f251, 0x9eeb, 0x494f, { 0x80, 0x45, 0x8a, 0xef, 0xd7, 0xf0, 0xef, 0x5 } };

// {9ADD3BC1-403A-4914-B892-A1C2B2D7DEE6}
static const GUID IID_ISQLiteClient = 
{ 0x9add3bc1, 0x403a, 0x4914, { 0xb8, 0x92, 0xa1, 0xc2, 0xb2, 0xd7, 0xde, 0xe6 } };

// {9CB47E38-B7B2-498a-838B-1F83FA35E048}
static const GUID IID_ISQLiteSecurityDB = 
{ 0x9cb47e38, 0xb7b2, 0x498a, { 0x83, 0x8b, 0x1f, 0x83, 0xfa, 0x35, 0xe0, 0x48 } };


typedef struct _sql_return
{
		static const int SQL_OK           = 0;   /* Successful result */
		/* beginning-of-error-codes */
		static const int SQL_ERROR        = 1;   /* SQL error or missing database */
		static const int SQL_INTERNAL     = 2;   /* Internal logic error in SQLite */
		static const int SQL_PERM         = 3;   /* Access permission denied */
		static const int SQL_ABORT        = 4;   /* Callback routine requested an abort */
		static const int SQL_BUSY         = 5;   /* The database file is locked */
		static const int SQL_LOCKED       = 6;   /* A table in the database is locked */
		static const int SQL_NOMEM        = 7;   /* A malloc() failed */
		static const int SQL_READONLY     = 8;   /* Attempt to write a readonly database */
		static const int SQL_INTERRUPT    = 9;   /* Operation terminated by sqlite3_interrupt()*/
		static const int SQL_IOERR       = 10;   /* Some kind of disk I/O error occurred */
		static const int SQL_CORRUPT     = 11;   /* The database disk image is malformed */
		static const int SQL_NOTFOUND    = 12;   /* NOT USED. Table or record not found */
		static const int SQL_FULL        = 13;   /* Insertion failed because database is full */
		static const int SQL_CANTOPEN    = 14;   /* Unable to open the database file */
		static const int SQL_PROTOCOL    = 15;   /* NOT USED. Database lock protocol error */
		static const int SQL_EMPTY       = 16;   /* Database is empty */
		static const int SQL_SCHEMA      = 17;   /* The database schema changed */
		static const int SQL_TOOBIG      = 18;   /* String or BLOB exceeds size limit */
		static const int SQL_CONSTRAINT  = 19;   /* Abort due to constraint violation */
		static const int SQL_MISMATCH    = 20;   /* Data type mismatch */
		static const int SQL_MISUSE      = 21;   /* Library used incorrectly */
		static const int SQL_NOLFS       = 22;   /* Uses OS features not supported on host */
		static const int SQL_AUTH        = 23;   /* Authorization denied */
		static const int SQL_FORMAT      = 24;   /* Auxiliary database format error */
		static const int SQL_RANGE       = 25;   /* 2nd parameter to sqlite3_bind out of range */
		static const int SQL_NOTADB      = 26;   /* File opened that is not a database file */
		
		static const int SQL_ERR_CONNECT = 210;   /* File opened that is not a database file */
		static const int SQL_ERR_NOT_CONNECTED = 211;
		static const int SQL_ERR_PARAM_ERROR = 212;
		static const int SQL_ERR_LOW_MEM = 213;
		static const int SQL_ERR_CONNECTION = 214;
		
		static const int SQL_ROW         = 100;  /* sqlite3_step() has another row ready */
		static const int SQL_DONE        = 101;  /* sqlite3_step() has finished executing */
}_sql_errors;

typedef struct _sql_db_open_typest
{
		static const int  SQL_OPEN_READONLY         = 0x00000001;  /* Ok for sqlite3_open_v2() */
		static const int  SQL_OPEN_READWRITE        = 0x00000002;  /* Ok for sqlite3_open_v2() */
		static const int  SQL_OPEN_CREATE           = 0x00000004;  /* Ok for sqlite3_open_v2() */
		static const int  SQL_OPEN_NOMUTEX          = 0x00008000;  /* Ok for sqlite3_open_v2() */
		static const int  SQL_OPEN_FULLMUTEX        = 0x00010000;  /* Ok for sqlite3_open_v2() */
		static const int  SQL_OPEN_SHAREDCACHE      = 0x00020000;  /* Ok for sqlite3_open_v2() */
		static const int  SQL_OPEN_PRIVATECACHE     = 0x00040000;  /* Ok for sqlite3_open_v2() */
}_sql_db_open_mode;



typedef int sql_stmt_handle;

class ISQLiteClient :public IUnknown
{
public:
	
	virtual bool sql_ping( DWORD& dwMiliSecDuration, int* p_out_AmountOfDataSent = NULL ) = 0;

	virtual int sql_connect( const char* server, 
							 int port , 
							 const char* username, 
							 const char* password, 
							 const char* database, 
							 int db_open_mode ) = 0;
	
	virtual int sql_prepair_v2( const char *zSql, sql_stmt_handle& iStmt ) = 0;
	virtual int sql_step( sql_stmt_handle& iStmt , int iBufferRows = 1 ) = 0;
	virtual int sql_finalize( sql_stmt_handle &iStmt ) = 0;
	virtual int sql_reset( sql_stmt_handle &iStmt ) = 0;
	virtual int sql_clear_bindings( sql_stmt_handle &iStmt ) = 0;

	virtual int sql_column_int(  sql_stmt_handle& iStmt , int iCol ) = 0;
	virtual const char* sql_column_text( sql_stmt_handle &iStmt, int iCol) = 0;
	virtual double sql_column_double( sql_stmt_handle &iStmt, int iCol ) = 0;
	virtual __int64 sql_column_int64( sql_stmt_handle& iStmt , int iCol ) = 0;
	virtual const void *sql_column_blob(  sql_stmt_handle& iStmt , int iCol ) = 0;

	virtual int sql_column_bytes( sql_stmt_handle& iStmt , int iCol) = 0;



	virtual int sql_column_count( sql_stmt_handle &iStmt ) = 0;
	virtual int sql_column_type( sql_stmt_handle &iStmt , int N ) = 0;
	virtual const char* sql_column_name( sql_stmt_handle &iStmt , int N ) = 0;
	
	//bind_xxxx()
	virtual int sql_bind_int( sql_stmt_handle &iStmt , int N , int iValue ) = 0;
	virtual int sql_bind_int64( sql_stmt_handle &iStmt , int N , __int64 iValue ) = 0;
	virtual int sql_bind_double( sql_stmt_handle &iStmt , int N , double iValue ) = 0;
	virtual int sql_bind_text( sql_stmt_handle &iStmt , int N , char* sValue , int iValLenght ) = 0;
	virtual int sql_bind_text16( sql_stmt_handle &iStmt , int N , void* sValue , int iValLenght ) = 0;
	virtual int sql_bind_blob( sql_stmt_handle &iStmt , int N , void* sValue , int iValLenght ) = 0;
	virtual int sql_bind_zeroblob( sql_stmt_handle &iStmt , int N , int iValLenght ) = 0;
	virtual int sql_bind_null( sql_stmt_handle &iStmt , int N ) = 0;



	
	virtual int sql_close()=0;
	//error report
	virtual const char* sql_errormsg( )=0;
	virtual int sql_errno( 	) = 0;
};





class IConnectionObserver
{
public:
	virtual BOOL ClientConnected( DWORD dwUniqueID , const char* szIP , int iPort )=0;
	virtual void ClientDisconnected( DWORD dwUniqueID , const char* szIP , int iPort )=0;
};


class IProtocolErrorObserver
{
public:
	virtual void ProtocolError( DWORD dwUniqueID , const char* szIP , int iPort )=0;
};

class ISQLiteServer :public IUnknown
{
public:
	
	virtual bool SetSecurityDatabase( const char* szFullPath )=0;
	virtual bool StartServer( int iPort = 6603 , bool bCreateThread = true )=0;
	virtual bool StopServer()=0;


	virtual void observer_add( IConnectionObserver* p )=0;
	virtual void observer_add( IProtocolErrorObserver* p )=0;
};





//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//user row representations
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
typedef struct _tagUsersData
{
	_tagUsersData()
	{id = 0;username = "";password = "";iPermissions = 0;}
	_tagUsersData(int idx , const char* usernamex, const char* passwordx, int iPermissionx )
	{id = idx;username = usernamex;password = passwordx;iPermissions = iPermissionx;}
	_tagUsersData( const _tagUsersData& cpy )
	{id = cpy.id;username = cpy.username;password = cpy.password;iPermissions = cpy.iPermissions;} 
	int id;
	string username;
	string password;
	int iPermissions;
}UsersData,*PUsersData;


//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//db_list row represetation
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
typedef struct _tagDBData
{
	_tagDBData()
	{id = 0;db_name=""; db_path=""; db_users_table="";}
	_tagDBData( int idx , const char* db_namex, const char* db_pathx, const char* db_users_tablex )
	{id = idx;db_name=db_namex; db_path=db_pathx; db_users_table=db_users_tablex;}

	_tagDBData( const _tagDBData& cpy )
	{id = cpy.id;db_name = cpy.db_name;db_path = cpy.db_path;db_users_table = cpy.db_users_table;} 

	int id;
	string db_name;
	string db_path;
	string db_users_table;

}DBData,*PDBData;


//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//avoid passing STL containers
//Deal with heap differences
//allocations/dealocations and
//SLT implementations differences
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
class IDBList
{
public: 
	virtual void add( int,const char*,const char*,const char*)=0;
};
class cdb_list :public IDBList
{
public:
	void add( int id , 
			  const char* db_name,
			  const char* db_path,
			  const char* db_users_table )
	{
		data.push_back( DBData(id,db_name,db_path,db_users_table ) );
	}
	vector<DBData> data;
};


class IURSERList
{
public: 
	virtual void add( int,const char*,const char*,int )=0;
};
class cuser_list :public IURSERList
{
public:
	void add( int id , 
			  const char* username,
			  const char* password,
			  int iPermission )
	{
		data.push_back( UsersData(id,username,password,iPermission ) );
	}
	vector<UsersData> data;
};



//ISQLiteSecurityDB helper interface to deal with the security db
class ISQLiteSecurityDB :public IUnknown
{
public:
	
	//open a security databse
	virtual bool OpenDB( const char* szFullPath ,			//path to the security database
						BOOL bCreateIfNoneExist = TRUE		//should the DB be created if it does not exist
						) = 0;

	//add an entry in the db_list and create the table if needed
	//creates all tables if they do not exit 
	virtual bool addDatabaseToList( 
							  const char* szBdName,
							  const char* szDBPath,
							  const char* szUsersTable = NULL,
							  const char* szUserName = NULL,
							  const char* szPassword = NULL,
							  int iPermissions = 16383 
							  ) = 0;

	//add username,password,permission given 1. table_name
	//creates table if it does not exit
	virtual bool addUserToTable( const char* szTable,
								 const char* szUserName,
								 const char* szPassword,
								 int iPermission = 16383  ) = 0;

	//add username,password,permission given 1. db_name
	//creates table if it does not exit
	virtual bool addUserToDB( const char* db_name,
								 const char* szUserName,
								 const char* szPassword,
								 int iPermission = 16383  ) = 0;




	//remove entry for database and optionally drop the users table that is linked with db_name
	virtual bool remDBandUserList( const char* db_name , BOOL bRemoveUsers = FALSE ) = 0;

	//remove user information table
	virtual bool remTable( const char* szTableName ) = 0;

	//remove user from table
	virtual bool remUser(const char* szTableName, const char* szUserName ) = 0;

	//remove user from database
	virtual bool remDBUser(const char* db_name, const char* szUserName ) = 0;


	
	//get a user record given 1.table_name 2.username
	virtual bool getUserRecord( const char* szTableName , const char* szUserName , IURSERList* data  ) = 0;

	//get the specific DB record given 1. db_name
	virtual bool getDBRecord( const char* szDBName , IDBList* p ) = 0;
	

	//get the entrie list of the databases in the db_list
	virtual bool getDBList( IDBList* p ) = 0;

	//get all entries from the User_list table given 1. tbale_Name
	virtual bool getUserList( const char* szTableName , IURSERList* data ) = 0;

	//update username given 1.table_name and 2. Old_username
	virtual bool updateUsernameInTable( const char* szTableName, const char* szOLDUserName , const char* szNewUserName ) = 0;

	//update username given 1.db_name and 2. Old_username
	virtual bool updateUsernameInDB( const char* szBDName, const char* szOLDUserName , const char* szNewUserName ) = 0;

	//update password given 1.table_name and 2. szUserName
	virtual bool updatePasswordInTable( const char* szTableName, const char* szUserName , const char* szNewPassword ) = 0;

	//update password given 1.db_name and 2. szUserName
	virtual bool updatePasswordInDB( const char* db_name, const char* szUserName , const char* szNewPassword ) = 0;

	//update permission given 1.table_name and 2. szUserName
	virtual bool updatePermissionInTable( const char* table_name, const char* szUserName , int iNewPermission ) = 0;

	//update permission given 1.db_name and 2. szUserName
	virtual bool updatePermissionInDB( const char* db_name, const char* szUserName , int iNewPermission ) = 0;

	//update db_path given 1.db_name
	virtual bool updateDBpath( const char* db_name, const char* new_path ) = 0;

	//update db_name given 1.db_name
	virtual bool updateDBname( const char* db_name, const char* new_name ) = 0;

	//update db_user_table given 1.db_name
	virtual bool updateDBuser_table( const char* db_name, const char* new_usertable ) = 0;

};


#endif //_ISQLQUERYAS_H_