/* 
 * This file is automaticaly generated, Please dont edit this file! 
 */
#include <sqlite.h> 































void sqlite_constructor( sqlite * this, char * filePath ) {
		this->value = "good";

		sqlite_connect( this,  filePath );

	}


void sqlite_connect( sqlite * this, char * filePath ) {

		printf("\n\ntrying to connect.. %s\n\n", filePath);

		int rc = sqlite3_open( filePath, & this->db );

		if ( rc != SQLITE_OK ) {

			printf( "Cannot open database: %s\n", sqlite3_errmsg( this->db ) );

			sqlite3_close( this->db );

			consoleManager_error( console,  ( char * ) sqlite3_errmsg( this->db ) );

			return;

		}

		rc = sqlite3_prepare_v2( this->db, "SELECT SQLITE_VERSION()", -1, & this->res, 0 );    

		if (rc != SQLITE_OK) {

			consoleManager_error( console,  ( char * ) sqlite3_errmsg( this->db ) );
			
			sqlite3_close( this->db );

			return;

		}

		rc = sqlite3_step(this->res);

		







		
		
	}

void sqlite_free( sqlite * this ) {

		sqlite3_finalize( this->res );

		sqlite3_close( this->db );

	}

void sqlite_selectModel( sqlite * this, char * className ) {

		this->selectedModel = className;

		











































	}

void sqlite_createTable( sqlite * this ) {

		char * errorMessage = 0;

		char *sql = "DROP TABLE IF EXISTS user;" 
		            "CREATE TABLE user( id INT, username TEXT, userlevel INT, hash TEXT );";

		int rc = sqlite3_exec(this->db, sql, 0, 0, &errorMessage);

		if ( rc != SQLITE_OK ) {
		    
		    printf( "SQL error: %s\n", errorMessage );
		    
		    sqlite3_free( errorMessage );

		    sqlite3_close(this->db);
		    
		    
		} 

	}





























































































































































void sqlite_addRows( sqlite * this, array * insertArray ) {

		array * copy	= insertArray;

		int classIndex 			= getClassIndexByClassName( this->selectedModel );

		text * query			= text_newPointer( "" );

		text_append( query,  "INSERT INTO " );

		text_append( query,  this->selectedModel );


		sqlite3_stmt * result;


		char * * propertyNames	= getPropertiesByClassIndex( classIndex );

		int propertyCount		= getPropertyCountByClassIndex( classIndex );

		int  * propertyOffsets	= getPropertyOffsetsByClassIndex( classIndex );

		int * datatypeIndices	= getPropertyDatatypeIndexesByClassIndex( classIndex );



		text_append( query,  " ( " );

		for (int propertyIndex = 0; propertyIndex < propertyCount; ++propertyIndex)
		{

			char * propertyName 		= propertyNames[propertyIndex];

			int datatype				= datatypeIndices[ propertyIndex ];

			if( datatype > 0 ) {

				
				continue;
				
			}

			if( propertyIndex > 0 ) {

				text_append( query,  ", " );

			}

			text_append( query,  propertyName );

		}

		text_append( query,  " ) " );

		text_append( query,  " VALUES ( " );

		for (int propertyIndex = 0; propertyIndex < propertyCount; ++propertyIndex)
		{

			int datatype				= datatypeIndices[ propertyIndex ];

			if( datatype > 0 ) {

				
				continue;
				
			}

			if( propertyIndex > 0 ) {

				text_append( query,  ", " );

			}

			text_append( query,  "?" );

		}

		text_append( query, " ) " );



		sqlite3_prepare_v2( this->db, query->value, -1, &result, 0 );

		sqlite3_exec(this->db, this->selectedModel, NULL, NULL, 0);

		sqlite3_exec(this->db, "PRAGMA synchronous = OFF", NULL, NULL, 0);

		sqlite3_exec(this->db, "PRAGMA journal_mode = MEMORY", NULL, NULL, 0);


		int insertItemCount		= copy->total;

		char * voidArray		= ( char * ) copy->items;

		

		for (int i = 0; i < insertItemCount; ++i)
		{
			char * pointer 		= array_get( copy,  i );

			sqlite_updateRow( this,  result, propertyCount, propertyNames, propertyOffsets, datatypeIndices, pointer );

			sqlite3_step( result );

			sqlite3_reset( result );

		}

		

		sqlite3_finalize( result );

		

	}



void sqlite_updateRow( sqlite * this, sqlite3_stmt * result,  int propertyCount,  char * * propertyNames,  int  * propertyOffsets,  int * datatypeIndices,  char * pointer ) {

		for (int propertyIndex = 0; propertyIndex < propertyCount; ++propertyIndex)
		{

			char * propertyName 		= propertyNames[propertyIndex];

			int propertyOffset			= propertyOffsets[propertyIndex];

			int propertyDatatypeIndex	= getPropertyDatatypeIndex( datatypeIndices, propertyIndex );

			

			if( propertyDatatypeIndex == -5 ) {

				int value	= *( int * )(pointer + propertyOffset);

				

				sqlite3_bind_int( result, propertyIndex + 1, value );

			} else if( propertyDatatypeIndex == -3 ) {

				

				uintptr_t * value				= ( uintptr_t * ) ( pointer + propertyOffset );

				

				

				sqlite3_bind_text( result, propertyIndex + 1, (char *) *value, -1, SQLITE_TRANSIENT  );

			}

		}

		

	}

void sqlite_update( sqlite * this, void * row ) {

		int classIndex 				= getClassIndexByClassName( this->selectedModel );

		char ** propertyNames		= getPropertiesByClassIndex( classIndex );

		int propertyCount			= getPropertyCountByClassIndex( classIndex );

		int  * propertyOffsets		= getPropertyOffsetsByClassIndex( classIndex );

		int * datatypeIndices		= getPropertyDatatypeIndexesByClassIndex( classIndex );

		int propertyIdOfIndex		= -1;


		for ( int i = 0; i < propertyCount; ++i )
		{
			char * propertyName	= propertyNames[i];

			

			if( strcmp( propertyName, "id" ) == 0 ) {

				propertyIdOfIndex = i;

				break;

			}
		}

		if( propertyIdOfIndex == -1 ) {

			printf("Class '%s' does not have an id field. ");

		}

		int idOffset		= propertyOffsets[ propertyIdOfIndex ];

		char * pointer		= row;

		int id				= *( pointer + idOffset );

		text * query		= text_newPointer( "" ); 

		text_append( query,  "UPDATE " );

		text_append( query,  this->selectedModel );

		text_append( query,  " SET " );

		int activePropertyCount = 0;

		
		for (int propertyIndex = 0; propertyIndex < propertyCount; ++propertyIndex)
		{

			char * propertyName 		= propertyNames[propertyIndex];

			int datatypeIndex			= datatypeIndices[propertyIndex];

			
			if( datatypeIndex > 0 ) {

				continue;

			}

			activePropertyCount++;

			if( propertyIndex > 0 ) {

				text_append( query,  ", " );

			}

			text_append( query,  propertyName );

			text_append( query,  " = ? " );

		}

		text_append( query,  " where id = ? " );

		sqlite3_stmt * result;

		sqlite3_prepare_v2( this->db, query->value, -1, &result, 0 );

		sqlite_updateRow( this,  result, propertyCount, propertyNames, propertyOffsets, datatypeIndices, pointer );

		sqlite3_bind_int( result, activePropertyCount + 1, id );

		

		sqlite3_step( result );

		sqlite3_finalize( result );

		

	}

void sqlite_addRow( sqlite * this, void * row ) {

		int classIndex 			= getClassIndexByClassName( this->selectedModel );

		text * query			= text_newPointer( "" );

		text_append( query,  "INSERT INTO " );

		text_append( query,  this->selectedModel );


		sqlite3_stmt * result;


		char * * propertyNames	= getPropertiesByClassIndex( classIndex );

		int propertyCount		= getPropertyCountByClassIndex( classIndex );

		int  * propertyOffsets	= getPropertyOffsetsByClassIndex( classIndex );

		int * datatypeIndices	= getPropertyDatatypeIndexesByClassIndex( classIndex );

		char * pointer 			= row;


		text_append( query,  " ( " );

		for (int propertyIndex = 0; propertyIndex < propertyCount; ++propertyIndex)
		{

			char * propertyName 		= propertyNames[ propertyIndex ];


			int datatype				= datatypeIndices[ propertyIndex ];

			if( datatype > 0 ) {

				
				continue;
				
			}


			if( propertyIndex > 0 ) {

				text_append( query,  ", " );

			}

			text_append( query,  propertyName );

		}

		text_append( query,  " ) " );

		text_append( query,  " VALUES ( " );

		for (int propertyIndex = 0; propertyIndex < propertyCount; ++propertyIndex)
		{

			int datatype				= datatypeIndices[ propertyIndex ];

			if( datatype > 0 ) {

				
				continue;
				
			}


			if( propertyIndex > 0 ) {

				text_append( query,  ", " );

			}

			text_append( query,  "?" );

		}

		text_append( query, " ) " );



		

			sqlite3_prepare_v2( this->db, query->value, -1, &result, 0 );

			sqlite_updateRow( this,  result, propertyCount, propertyNames, propertyOffsets, datatypeIndices, pointer );

			sqlite3_step( result );
			
		

		sqlite3_finalize( result );

		

	}

struct array * sqlite_fetchRows( sqlite * this, char * sql ) {

		sqlite3_stmt * result;

		int rc 					= sqlite3_prepare_v2( this->db, sql, -1, &result, 0 );

		if ( rc != SQLITE_OK ) {

			printf("Failed to execute statement: %s\n", sqlite3_errmsg( this->db ) );

		}








		int rowIndex 			= 0;


		

		int classIndex 			= getClassIndexByClassName( this->selectedModel );


		


		int propertyIndex 		= getPropertyIndexByPropertyName( classIndex, "username" );

		int propertyCount		= getPropertyCountByClassIndex( classIndex );

		char ** propertyNames	= getPropertiesByClassIndex( classIndex );

		int  * propertyOffsets	= getPropertyOffsetsByClassIndex( classIndex );

		int * datatypeIndices	= getPropertyDatatypeIndexesByClassIndex( classIndex );


		char * shortPointer		= malloc( sizeof( char * ) * 100000 );

		void * * voidArray		= malloc( sizeof( void * ) * 100000 );

		int  structByteSize;
		
		getArrayByClassIndex( 1000, voidArray, &structByteSize, classIndex );

		shortPointer = ( char * ) shortPointer;
 

		while ( sqlite3_step( result ) != SQLITE_DONE ) { 

			 

				int pointerIndex 		= ( rowIndex * ( structByteSize ) );

				

				char * pointer 			= shortPointer + pointerIndex;

			 	int columnCount 		= sqlite3_data_count( result );

			 	

			 	for (int i = 0; i < columnCount; ++i)
			 	{

					const char * columnName 	= sqlite3_column_name( result, i );

					const int propertyIndex 	= getPropertyIndexByPropertyName( classIndex, (char *)columnName );

					int propertyDatatypeIndex	= getPropertyDatatypeIndex( datatypeIndices, propertyIndex );

					int propertyOffset			= getPropertyOffsetByPropertyIndex( propertyOffsets, propertyIndex );

					

					

					

					

					if( propertyDatatypeIndex == -5 ) {

						const int columnValue 		= sqlite3_column_int( result, i );

	
						*( int * )( pointer + propertyOffset ) 	= columnValue; 

					} else if( propertyDatatypeIndex == -3 ) {

						const char * columnValue 	= sqlite3_column_text( result, i );

						char * columnValueCopy		=  malloc( strlen( columnValue ) );

						strncpy( columnValueCopy, columnValue, strlen( columnValue ) );

						


						

						memcpy( pointer + propertyOffset, &columnValueCopy, 8 );

					}

					

			 }


			voidArray[rowIndex] = pointer;

	

			rowIndex++;

		}

		struct array * rows = array_newPointer();

		rows->items		= voidArray;

		rows->total		= rowIndex;

		return rows;

	}

sqlite sqlite_new(char * filePath) {

	sqlite instance;

	instance.__classIndex = 27;

	sqlite_constructor( &instance, filePath);

	return instance;

}

sqlite * sqlite_newPointer(char * filePath) {

	struct sqlite * pointer = malloc( sizeof ( struct sqlite ) );

	pointer->__classIndex = 27;

	sqlite_constructor( pointer , filePath);

	return pointer;

}

