


// Classes

// #include <classConfiguration.h>

#define LINUX

#include <user.h>

#include "text.h"

#include "vector2.h"

#include "vector3.h"

#include "triangle.h"

#include "array.h"

#include "fileSystem.h"

#include "sqlite.h"

#include "char.h"

#include "int.h"

#include "extends.h"

#include "toolset.h"

#include "console.h"

#include "street.h"

#include "opengl.h"


// C includes

#include <time.h>

#include <pthread.h>

#include <sys/sysinfo.h>

       


#include <stdlib.h>

#include <stdio.h>

     

#include <sched.h>






// globals

char * someArray[10] = {"a", "b", "c"};





void startOpenGL() {

	opengl * instance = new opengl();

	instance->initialize();


}

/*

class thread{

	int index;

	int vectorCount;

}



void multiThread() {

	clock_t tic 		= clock();

	printf("This system has %d threads configured and %d threads available.\n", get_nprocs_conf(), get_nprocs());


 	int vectorCount			= 10000;

 	int numberOfThreads		= get_nprocs();

	pthread_t thread[numberOfThreads];
	
	for (int i = 0; i < numberOfThreads; ++i)
	{

		struct thread data 	= new thread();

		data.index			= i;

		data.vectorCount	= vectorCount;


		pthread_create( &thread[i],		 NULL,		  mythread2,		   &data );

	}


	//waiting for completion

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

		pthread_join( thread[i], NULL );

		printf("Thread %i has finished\n\n", i);

	}

	clock_t toc 		= clock();

	printf("\n\nAll threads have finished\n\n");


	printf("Multiply: %f seconds, Threads: %i   Vectors:	%i\n\n\n", (double)( toc - tic ) / CLOCKS_PER_SEC, numberOfThreads, numberOfThreads * vectorCount );



	printf("Now doing the same total number of vector additions on only the main thread.\n\n");

	tic 				= clock();


	struct thread data 	= new thread();

	data.index			= 0;

	data.vectorCount	= numberOfThreads * vectorCount;

	mythread2( &data );


	toc 		= clock();

	printf("Multiply: %f seconds, Threads: 1   Vectors:	%i\n", (double)( toc - tic ) / CLOCKS_PER_SEC, numberOfThreads * vectorCount );


}

static void * mythread2( void * args) {

	struct thread * currentThread 		= ( struct thread * ) args;

	clock_t tic 		= clock();

	int threadIndex			= currentThread->index;

	int vectorCount			= currentThread->vectorCount;


	vector3 * newVector3 	= new vector3();

	newVector3->x	= 0;

	newVector3->y	= 2;

	newVector3->z	= 3;


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

		vector3  vector3B 	= new vector3();

		vector3B.x	= 1;

		vector3B.y	= 3;

		vector3B.z	= 4;



		vector3  vector3C = new vector3();

		vector3C.x	= 0;

		vector3C.y	= 3;

		vector3C.z	= 4;

		//newVector3	= vector3C + ( vector3C + newVector3 + ( ( ( ( vector3B + vector3C ) ) + vector3C ) + vector3B ) );

		newVector3	= newVector3 + ( ( vector3B + vector3C ) + vector3C );

		//printf("thread %i:	x: %i 		y: %i	 z:	%i \n", threadIndex, newVector3->x, newVector3->y, newVector3->z);

	}

	clock_t toc 		= clock();

	printf("\nThread .., threadIndex: %i finished, time:	%f		Computing %i * 2 vectors.\n\n\n",  threadIndex, (double)( toc - tic ) / CLOCKS_PER_SEC, vectorCount);

	return NULL;
}

void textAndArraysExamples() {


	clock_t tic 			= clock();

	text * sometext			= new text(" my first text");

	struct text * a 			= new text(" Mooi ");

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

		sometext->appendObject( a )->append("something");

	}

	//printf("append: %s \n\n", sometext->buffer);

	clock_t toc = clock();

	printf("Multiply: %f seconds\n", (double)( toc - tic ) / CLOCKS_PER_SEC);


	char * testText			= "a,"; 

	array * splitParts 		= testText->concatenate( "b, " )->concatenate("c,d,e")->concatenate(",f ")->split(",g");

	char * compareString 	= "something";

	splitParts.unshift((char *) "first");

	splitParts.unshift((char *) "this first");


	printf( "joined: %s\n\n", splitParts.join(", ") );

	char * lastElement	= splitParts->pop();

	printf( "pop joined: %s\n\n", splitParts.join(", ") );

	printf( "pop removed element: %s\n\n", lastElement );


	if( compareString.compare("something") ) {

		printf("this is true\n");

	} else {

		printf("this is not true\n");

	}

	printf("first:		%s \n\n", splitParts.get( 0 ) );

	int splitCount			= splitParts->length();

	printf("splitCount: %i\n",  splitCount);

	for (int i = 0; i < splitCount; ++i)
	{
		
		char * splitPart	= splitParts.get( i );

		//printf("splitPart:		%s \n\n", splitPart->trim() );

	}


}



void sqlite3Example() {

	// sqlite * sql 				= new sqlite("./database/users.sqlite");

	sqlite * sql 				= new sqlite(":memory:");

	sql->selectModel( "user" );


	sql->createTable();

	char * names[20]			= { "piet", "gurbe", "siebe", "gerben", "twain", "piet", "gurbe", "siebe", "gerben", "twain", "piet", "gurbe", "siebe", "gerben", "twain" };

	clock_t tic 				= clock();


	array * usersInsertArray 	= new array();

	for (int i = 0; i <10; ++i) //20000
	{
	
		char * name = names[i];

		struct user * userInstance = new user();

		userInstance->id		= i;

		userInstance->username 	= name;

		userInstance->userlevel	= 3;

		userInstance->hash		= "12345";

		usersInsertArray.add( userInstance );

		//sql->addRow( userInstance );

	}


	sql->addRows( usersInsertArray );



	clock_t toc = clock();

	printf("Multiply: %f seconds, rows: %i\n", (double)( toc - tic ) / CLOCKS_PER_SEC, 10000);



	array * usersA 	= sql->fetchRows( "SELECT * FROM user" );

	//user * firstUser = new user();

	user * firstUser = usersA->get( 1 );

	//firstUser->id =10;

	firstUser->username		= "updated";

	firstUser->userlevel	= 1111;

	firstUser->hash			= "new hash";

	console->log( "??", firstUser, "Yeey console.log workswith , , " );

	sql->update( firstUser );

	printf("before log\n\n");


	

	array * users 	= sql->fetchRows( "SELECT * FROM user  " );

	int userCount	= users->total;
	

	printf("added rows: %i\n", userCount);

	console->createHorisontalLine();
	printf("\e[1m");

	printf("	");

	printf("%-20s", "id" );

	printf("%-30s", "username" );

	printf("%-20s", "userLevel" );

	printf("%-30s", "Hash");

	printf("\e[m");

	printf("\n");

	console->createHorisontalLine();

	printf("users: %i\n", userCount);

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

		struct user * userInstance = users->get( i );

		userInstance->id;

		userInstance->username;

		printf("	");

		printf("%-20i", userInstance->id);

		printf("%-30s", userInstance->username);

		printf("%-20i", userInstance->userlevel);

		printf("%-30s", userInstance->hash);

		printf( "\n" );//%-30s

	}

	sql->free();

	console->createHorisontalLine();

}

void multiInherintence() {



	struct inherit * pointer 	= new inherit();

	//pointer->propertyFromC = 20;


	printf("pointer->propertyFromC: %i\n\n", pointer->propertyFromC );

	pointer->methodFromC();

	printf("\n\n\n\n");


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

		struct inherit instance = new inherit();

		instance.propertyFromA = i;

		instance.propertyFromB = i;

		instance.propertyFromC = i;

		instance.methodFromC();

	}

}
*/


//int main()
//{

	//startOpenGL();

/*
	return 1;

	struct user	* newUser		= new user();

	newUser->id		= 1;

	newUser->username	= "peter";

	newUser->userlevel	= 2134;

	newUser->hash		= "#234234325";



	struct array * addresses = newUser->addresses;


	address * someAddress = new address();

	someAddress->street = "HiLane";

	someAddress->number	= 1234;

	addresses->add( someAddress );




	address * otherAddress = new address();

	otherAddress->street = "OtherLane";

	otherAddress->number	= 4567;

	addresses->add( otherAddress );

	// todo   newUser->addresses->add( otherAddress );


	printf("adresses count: %i\n\n", addresses->length() );


	char * something 	= "this is from an char * ";

	int somethingElse	= 123;


	console.log( 	"Goedendag", 
					123456, 
					"en een andere text.", 
					something, 
					somethingElse, 
					"something en something", 
					"in native c", 
					23456, 
					newUser, 
					"and some text again" ); //&(int[3]){ 1, 2, 1 }, 3, 


	

	sqlite3Example();

	textAndArraysExamples();


	multiInherintence();

	//tools->createHorisontalLine();
	
	//createHorisontalLine();


	printf("\n\n\n\n\n\n\n");


	int totalInteger = 0;

	printf("This just works out of the box.. \n");

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

		int	someInteger = 10;

		int theNegative = someInteger->negative();

		totalInteger += theNegative;

		//printf("this int is negative: %i\n\n", someInteger->negative() );

	}



	char somechar				= 56;


	char * directory2			= "./assets/";

	fileSystem * filesystem 	= new fileSystem();

	char * directory			= "./assets/";

	array * files 				= filesystem->readDir( directory );

	int fileCount 				= files->length();

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

		char * file 	= files->get( i );

		char * path		= directory->concatenate( file );

		text * source 	= filesystem->readFile( path, "binary" );


		printf("filename: 	%s\n", path);

		printf("source: 	%s\n\n\n", source->value);

	}


	array * arrayA = new array();

	clock_t tic 		= clock();


	int count = 0;

	for (int i = 0; i < 1000000; ++i)
	{
		vector2 testVector 		= new vector2( i, i * 450 );

		vector2 testVector2 	= new vector2( 10, 450 );

		testVector->add( &testVector2 );

		count++;

	}


	printf("count: %i\n", count);


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

		vector2 testVector = new vector2( 10, 450 );


		arrayA->add( &testVector );

		arrayA->add( &testVector );


		//printf("number of items in array: %i \n ", arrayA->length()  );

		vector2 * returned = arrayA->get( i );

		//printf("returned vector x: %i \n ", returned->x );

		//printf("returned vector y: %i \n ", returned->y );

		vector2 testVector3 = new vector2( 2, 3 );

		arrayA->set( i, &testVector3 );

		vector2 * secondReturn = arrayA->get( 0 );

		//printf("returned vector x: %i \n ", secondReturn->x );

		//printf("returned vector y: %i \n ", secondReturn->y );

		returned->add( secondReturn );

		printf( "returned vector x: %i \n ", returned->x );

		printf("returned vector y: %i \n ", returned->y );

	}


	for ( int i = 0; i < 1; ++i )
	{
		
		vector2 a = new vector2( 10, 10 );

		vector2 b = new vector2( 10, 10 );

		a->add( &b );

		printf( "a->x: %i, a->y: %i\n", a.x, a.y);

	}

	

	for (int i = 0; i < 1; ++i)
	{
		triangle * a = new triangle();

		triangle * b = new triangle();


		a->add( b );
	}


	vector2 * t = new vector2( 2,2 );

	int totalLength = 0;

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

		t->x = 100;

		vector2 b = new vector2( 123, 2 );

		b.x = 50;

		vector2 c = new vector2( 1, 12 );


		c.x = i;

		t->add( &b );

		b.add( &c );

		c.add( &b );

		printf("a, %i\n", t->x);

		printf("b, %i\n", b.x);

		printf("c, %i\n", c.x);

	}



	operatorOverload();

	//printf("%s", other);

	*/

}
/*
void operatorOverload() {

	text * textB			= new text("ook mooi");

	char * other			= malloc(5000);

	vector3 * newVector3 	= new vector3();

	newVector3->x	= 2;

	newVector3->y	= 2;

	newVector3->z	= 3;


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

		vector3 * vector3B 	= new vector3();


		vector3B->x	= 2;

		vector3B->y	= 3;

		vector3B->z	= 4;


		vector3 * vector3C = new vector3();


		vector3C->x	= 2;

		vector3C->y	= 3;

		vector3C->z	= 4;

		newVector3	= vector3C + ( vector3C + newVector3 + ( ( ( ( vector3B + vector3C ) ) + vector3C ) + vector3B ) );

		newVector3	= newVector3 + ( ( vector3B + vector3C ) + vector3C );

	}

	console->log( newVector3 );

	text * textA		= new text("mooi");
	
	if( textA == textB ) {

		printf("mooi zo");

	}

	text * textC		= new text("mooi");

	text * textD		= new text("mooi");

	
	if( ( ( textA == textC ) && ( textA == textD ) ) && textA == textD ) {

		printf("Good, This works.\n\n");

	}

	char * realChar = "something";

	if( "something" == realChar ) {

		printf("Wauw.\n\n");

	}

	if( realChar == "something" ) {

		printf("Wauw.\n\n");

	}

	if( realChar == realChar ) {

		printf("Wauw.\n\n");

	}

	if( "something" == "something" && realChar == "something" ) {

		printf("Wauw.\n\n");

	}

	char * fancy	= "aaa ";

	char * aaaa		= " bbb ";

	char * bbbb		= " ccc ";

	char * dddd		= " dddd ";

	other += ( fancy + ( bbbb +  aaaa ) + dddd ) + " eee" + " het is een wonder ";

	other += ("boven wonder" + returnText("this is a normal function") + " and this " + ( "works just good..." + dddd )); 

	other += "something" +  ( returnText("this is a normal function") + textB->toNative() + textB->value );

	other +=  ("and here some text") + (textB->toNative()) ;

	other +=  (  textB->value + ( ( textB->value ) + returnText("this is a normal function") ) + (textB->toNative() + "here some text" + textB->value ) );

	other +=  textB->value + textB->value + ( textB->value + textB->value ) +  ( textB->value + textB->value ) + textB->value + textB->value;

	console.log( "Mooi zo ", other );


	multiThread();

	vector3 * VectorTester 	= new vector3();
*/
//}


char * returnText( char * text ) {

	return text;
}

void abort() {


}
