
#include "file.h"

int globalClassIndex	= 0;

struct file * file_new() {

	struct file * fileInstance 			= malloc( sizeof( struct file ) );

	return fileInstance;

}

void file_parseMacros( struct file * fileInstance, struct array * files ) {

	file_removeComments( fileInstance );

	char * filename 				= fileInstance->filename;

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


	char * source					= fileInstance->source;

	printf("%s\n\n", source);

	int includeCount					= array_length( fileInstance->includes );

	printf("add includes. %i \n", includeCount);
	
	for ( int k = 0; k < includeCount; ++k )
	{
		
		struct include * includeInstance	= array_get( fileInstance->includes, k );

		char * currentInclude				= includeInstance->path;

		char * includeFileName				= file_getFileNameFromInclude( currentInclude );

		char * includeFileBaseName			= file_removeExtensionFromFileName( includeFileName );



		struct file * includedFileInstance 	= file_getFileByFileName( files, includeFileBaseName );

	
		if( includedFileInstance != NULL ) {

			printf("loaded %s.h \n\n", includedFileInstance->path );

		} else {

			text * filePath	= text_new("/usr/include/");

			text_append( filePath, includeFileName );

			text_append( filePath, ".h" );


			if( fileSystem_exists( filePath->value ) ) {

				includedFileInstance 			= file_new();


				includedFileInstance->filename 				= basename( text_copy( filePath->value  ) );

				includedFileInstance->dirname	 			= dirname( text_copy( filePath->value  ) );

				includedFileInstance->path	 				= filePath->value;

				printf("Created new file:		%s\n\n", includedFileInstance->path);


				includedFileInstance->source				= fileSystem_readFile(  includedFileInstance->path  );


				//printf("%s\n\n", includedFileInstance->source);

			}

		}

		file_parseMacros( includedFileInstance, files );

	}

}

void file_extendClasses( struct file * fileInstance ) {

	//printf( ANSI_COLOR_YELLOW "\n\n\n		extend class.\n" ANSI_COLOR_RESET );

	struct array * classes	= fileInstance->classes;

	int classesCount		= array_length( classes );

	for (int i = 0; i < classesCount; ++i)
	{
		
		struct class * classInstance 	= array_get( classes, i );

		classInstance->hasExtended		= -1;

	}

	for (int i = 0; i < classesCount; ++i)
	{
		
		struct class * classInstance = array_get( classes, i );

		class_extendClass( classInstance );

	}

}

void file_extractTemplates( struct file * fileInstance ) {

	struct array * classes	= fileInstance->classes;

	int classesCount		= array_length( classes );

	for (int i = 0; i < classesCount; ++i)
	{
		
		struct class * classInstance 	= array_get( classes, i );

		int methodCount = array_length( classInstance->methods );

		for ( int k = 0; k < methodCount; ++k )
		{
			
			struct method * methodInstance 	= array_get( classInstance->methods, k );

			methodInstance->bodyOriginal 	= method_extractTemplates( methodInstance->bodyOriginal );

		}

	}

	struct array * functions	= fileInstance->functions;

	int functionCount	= array_length( functions );

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

		struct functionLayout * functionInstance = array_get( functions, i );

		functionInstance->bodyOriginal			= method_extractTemplates( functionInstance->bodyOriginal );


	}

}

char * class_createRegexSearchNeedle( char * name ) {

	char * replaceFromRegex		= "\\b";

	replaceFromRegex = text_concatenate( replaceFromRegex, name );

	replaceFromRegex = text_concatenate( replaceFromRegex, "\\b" );

	return replaceFromRegex;

}


void class_copyMethod( 	struct class * classInstance, 
						struct method * methodInstance, 
						struct class * classCopy, 
						int * lineNumber, 
						char * classNameRegex, 
						char * templateAgumentRegex, 
						char * firstTemplateArgument,
						char * firstTemplateArgumentValue ) {


	struct method * methodCopy		= malloc( sizeof( struct method ) );

	methodCopy->methodName			= methodInstance->methodName;

	methodCopy->isSetter			= methodInstance->isSetter;

	methodCopy->isGetter			= methodInstance->isGetter;

	methodCopy->returnType			= text_copy( methodInstance->returnType );

	*lineNumber						+= text_countLineBreaks( methodInstance->bodyOriginal, -1 ) + 10;

	methodCopy->lineNumber			= *lineNumber;

	methodCopy->arguments			= array_new();

	int argumentsCount				= array_length( methodInstance->arguments );

	for (int l = 0; l < argumentsCount; ++l)
	{
		char * currentArgument 			= array_get( methodInstance->arguments, l );

		char * argumentCopy				= text_copy( currentArgument );

		if( l == 0 ) {

			argumentCopy = text_regexReplaceAll( argumentCopy, classNameRegex, classInstance->className, classCopy->className );

		}

		array_add( methodCopy->arguments, argumentCopy );

	}
	

	methodCopy->variables = array_new();

	method_addThisVariableToVariables( classCopy, methodCopy->variables );

	methodCopy->bodyOriginal 		= text_regexReplaceAll( methodInstance->bodyOriginal, templateAgumentRegex, firstTemplateArgument, firstTemplateArgumentValue );//methodInstance->bodyOriginal;


	for ( int h = 0; h < argumentsCount; ++h )
	{

		char * currentArgument 		= array_get( methodCopy->arguments, h );

		currentArgument				= text_regexReplaceAll( currentArgument, templateAgumentRegex, firstTemplateArgument, firstTemplateArgumentValue );

		array_set( methodCopy->arguments, h, currentArgument );
		
	}


	methodCopy->returnType		= text_regexReplaceAll( methodCopy->returnType, templateAgumentRegex, firstTemplateArgument, firstTemplateArgumentValue );

	array_add( classCopy->methods, methodCopy );

}

void class_copyMethods( struct class * classInstance, struct class * classCopy, char * firstTemplateArgument, char * firstTemplateArgumentValue, int * lineNumber ) {

	char * templateAgumentRegex				= class_createRegexSearchNeedle( firstTemplateArgument );

	char * classNameRegex					= class_createRegexSearchNeedle( classInstance->className ); // "\\b TT \\b"


	int methodCount = array_length( classInstance->methods );

	for (int k = 0; k < methodCount; ++k )
	{
		
		struct method * methodInstance = array_get( classInstance->methods, k );

		class_copyMethod( classInstance, methodInstance, classCopy, lineNumber, classNameRegex, templateAgumentRegex, firstTemplateArgument, firstTemplateArgumentValue );

	}

}

void class_copyProperties( struct class * classInstance, struct class * classCopy, char * firstTemplateArgument, char * firstTemplateArgumentValue ) {

	char * replaceFromRegex				= class_createRegexSearchNeedle( firstTemplateArgument );


	int propertyCount 					= array_length( classInstance->properties );

	for (int k = 0; k < propertyCount; ++k )
	{
		
		struct property * propertyInstance 	= array_get( classInstance->properties, k );

		struct property * propertyCopy		= malloc( sizeof( struct property ) );

		propertyCopy->propertyName			= text_copy( propertyInstance->propertyName );

		propertyCopy->datatype				= text_copy( propertyInstance->datatype );

		propertyCopy->decleration			= text_copy( propertyInstance->decleration );

		propertyCopy->value					= text_copy( propertyInstance->value );

		propertyCopy->isPointer				= propertyInstance->isPointer;

		propertyCopy->type					= text_copy( propertyInstance->type );

		propertyCopy->hasValue				= propertyInstance->hasValue;

		propertyCopy->decleration			= text_regexReplaceAll( propertyCopy->decleration, replaceFromRegex, firstTemplateArgument, firstTemplateArgumentValue );

		propertyCopy->datatype				= text_regexReplaceAll( propertyCopy->datatype, replaceFromRegex, firstTemplateArgument, firstTemplateArgumentValue );


		array_add( classCopy->properties, propertyCopy );

	}

}

void class_instantiateTemplates( struct file * fileInstance, struct class * classInstance, int * lineNumber ) {

	struct template * currentTemplate 	= classInstance->template;

	array * intances					= currentTemplate->instances;

	array * arguments					= currentTemplate->arguments;


	printf("\n\n\n\n Creating %i templates for %s\n\n\n\n\n", array_length( intances ), classInstance->className );

	int intancesCount = array_length( intances );

	for ( int j = 0; j < intancesCount; ++j )
	{
		
		struct templateInstance * currentTemplateInstance 	= array_get( intances, j );


		char * firstTemplateArgumentValue	= array_get( currentTemplateInstance->argumentValues, 0 );  // array * <int>

		char * firstTemplateArgument		= array_get( arguments, 0 ); // template<T> 


		struct class * classCopy 			= class_new();

		classCopy->methods 					= array_new();

		classCopy->properties 				= array_new();

		classCopy->extends 					= array_new();

		classCopy->classIndex				= classInstance->classIndex;


		char * newClassName 				= text_copy( classInstance->className );







		newClassName 						= text_concatenate( newClassName, "_" );

		newClassName 						= text_concatenate( newClassName, firstTemplateArgumentValue );


		newClassName						= text_replaceAll( newClassName, "*",  "_pointer" );

		newClassName						= text_removeAllWhiteSpaces( newClassName );



		classCopy->className				= newClassName;


		class_copyMethods( classInstance, classCopy, firstTemplateArgument, firstTemplateArgumentValue, lineNumber );

		class_copyProperties( classInstance, classCopy, firstTemplateArgument, firstTemplateArgumentValue );


		classCopy->hasReflection	= classInstance->hasReflection;

		classCopy->usesTemplate		= true;


		array_add( fileInstance->classes, classCopy );

		array_add( allClasses, classCopy ); 

		// printf("replacing replaceFrom:	%s		namespace:	%s\n\n", firstTemplateArgument, firstTemplateArgumentValue);

		// printf("\n\n\n\n\n\n\nAdding class to allClasses:		'%s'\n\n\n\n\n\n\n", classInstance->className);	

		// array_add( fileInstance->classes, classCopy ); 

	}

}

void file_instanciateTemplates( struct file * fileInstance ) {

	int lineNumber 				= 0;

	struct array * classes		= fileInstance->classes;

	int classesCount			= array_length( classes );

	for (int i = 0; i < classesCount; ++i)
	{
		
		struct class * classInstance 	= array_get( classes, i );

		if( classInstance->usesTemplate ) {

			class_instantiateTemplates( fileInstance, classInstance, &lineNumber );

		}


	}

}


void file_composeHeaderMacros( struct file * fileInstance, struct text * classHeader ) {

	text_append( classHeader, "\n// Macros\n" );

	int macroCount = array_length( fileInstance->macros );

	for (int i = 0; i < macroCount; ++i)
	{
		
		char * currentMacro = array_get( fileInstance->macros, i );

		text_append( classHeader, "\n" );

		text_append( classHeader, currentMacro );

		text_append( classHeader, "\n" );

	}

	text_append( classHeader, "\n\n" );

}


void file_compose( struct file * fileInstance, struct application * applicationInstance ) {

	char * filename						= fileInstance->filename;

	struct text * classHeader			= file_composeHeaderIncludes( fileInstance );

	struct array * sourceArray 			= array_new();

	struct array * classes				= fileInstance->classes;

	int classesCount					= array_length( classes );

	for (int i = 0; i < classesCount; ++i)
	{
		
		struct class * classInstance = array_get( classes, i );

		if( i == 0 ) {

			if( classInstance->usesTemplate  ) {

				continue;

			}

		}

		

		class_composeHeader( classInstance,  classHeader, filename );

		class_composeMethods( classInstance,  classHeader, sourceArray );

	}

	file_composeFunctions( fileInstance->functions,  sourceArray, classHeader );

	file_writeAll( sourceArray, classHeader, fileInstance->path, fileInstance->classes, fileInstance->globals, fileInstance->path, applicationInstance );


}

void file_addIncludesToHeader( struct text * classHeader, struct file * currentFile ) {

	text_append( classHeader, "\n" );

	text_append( classHeader, "#include \"stdlib.h\"\n\n" );

	//text_append( classHeader, "#include \"classConfiguration.h\"\n\n" );

	text_append( classHeader, "extern char * __ClassNames[];\n\n" );

	text_append( classHeader, "\n// Includes\n" );

	int includesCount = array_length( currentFile->includes );

	for (int i = 0; i < includesCount; ++i)
	{
		
		struct include * includeInstance	= array_get( currentFile->includes, i );

		char * currentInclude = includeInstance->path;

		if( includeInstance->enabled ) {

			text_append( classHeader, "\n" );

			text_append( classHeader, currentInclude );

			text_append( classHeader, "\n" );

		}

	}

	text_append( classHeader, "\n\n" );

	
}

void file_preventDoubleLoadingHeader( struct text * classHeader, char * filename ) {

	// . with _
	filename = text_replaceChar( filename, 46, 95 );




	text_append( classHeader, "#ifndef _" );

	text_append( classHeader, filename );

	text_append( classHeader, "\n\n#define _" );

	text_append( classHeader, filename );

	text_append( classHeader, "\n\n" );

}

struct text * file_composeHeaderIncludes( struct file * currentFile ) {

	char * filename		= ( currentFile->filename );



	struct text * classHeader 	= text_new("");

	file_preventDoubleLoadingHeader( classHeader, filename );

	file_composeHeaderMacros( currentFile, classHeader );

	file_addIncludesToHeader( classHeader, currentFile );

	return classHeader;

}


void file_extractMethodsAndProperties( struct file * fileInstance ) {

	char * source				= fileInstance->source;

	array * classesArray		= array_new();

	lexer * currentLexer		= lexer_new();

	fileInstance->functions 	= array_new();


	lexer_getTokens( currentLexer, source );

	lexer_sortKeys( currentLexer );


	int count 				= lexer_length( currentLexer );

	int bodyCloseIndex		= -1;

	int depth				= 0;


	for (int i = count - 1; i >= 0; --i)
	{

		char * token 		= lexer_getToken( currentLexer, i );

		int key 			= lexer_getKey( currentLexer, i );


		if ( strcmp( token, "{" ) == 0 ) {

			depth++;

		}

		if( depth == 0 ) {

			if ( strcmp( token, "class" ) == 0 ) {

				file_extractInnerClass( currentLexer, i, key, fileInstance, source, bodyCloseIndex );

			}  

		}

		if ( strcmp( token, "}" ) == 0 ) {

			depth--;

		}


	}


}


void file_extractFunctions( struct file * fileInstance ) {

	char * source				= fileInstance->source;

	array * classesArray		= array_new();

	lexer * currentLexer		= lexer_new();

	fileInstance->functions 	= array_new();


	lexer_getTokens( currentLexer, source );

	lexer_sortKeys( currentLexer );


	int count 				= lexer_length( currentLexer );

	int bodyCloseIndex		= -1;

	int depth				= 0;


	for (int i = count - 1; i >= 0; --i)
	{

		char * token 		= lexer_getToken( currentLexer, i );

		int key 			= lexer_getKey( currentLexer, i );


		if ( strcmp( token, "{" ) == 0 ) {

			depth++;

		}

		if( depth == 0 ) {

			if ( strcmp( token, "(" ) == 0 ) {

				file_extractFunction( currentLexer, i, key, fileInstance, source, bodyCloseIndex, classesArray );

			}
			
		}

		if ( strcmp( token, "}" ) == 0 ) {

			depth--;

		}


	}


}


void file_parseClassBody(	lexer * currentLexer,
							int fromKey, 
							int toIndex, 
							char * source, 
							struct file * fileInstance, 
							struct class * classInstance ) {


	int depth 				= -1;

	int parsintMethod		= -1;

	printf("	class %s{\n\n", classInstance->className);

	for (int i = fromKey; i < toIndex; ++i)
	{
		int key					= lexer_getKey( currentLexer, i );

		char * currentToken 	= lexer_getToken( currentLexer, i );

		if ( strcmp( currentToken, "{" ) == 0 ) {

			depth++;

		}

		if( depth == 0 ) {

			//printf( "parseClassBody: %s		: %i\n", currentToken, (int) key );
			
			if ( strcmp( currentToken, ";" ) == 0 ) {

				class_extractProperty( currentLexer, key, i, source, classInstance );
	
			}


			if ( strcmp( currentToken, "(" ) == 0 && parsintMethod == -1 ) {

				int argumentCloseIndex					= text_findArgumentCloseIndex( source, key );

				int firstNextCharacter					= text_findFirstNextCharacterNotWhiteSpace( source, argumentCloseIndex );

				int beforePrevious						= lexer_getKey( currentLexer, i - 2 );

				char * methodDecleration 				= text_removeWhiteSpaces( text_slice( source, beforePrevious, firstNextCharacter ) );

	
				// () {
				if( source[firstNextCharacter] != 123 ) {

					continue;

				}

				class_extractMethod( currentLexer, source, i, classInstance, fileInstance->classes, fileInstance->functions );

				parsintMethod = 1;

			}

		}

		if ( strcmp( currentToken, "}" ) == 0 ) {

			depth--;

			parsintMethod = -1;

		}
		
	}

	printf("\n");

}

void file_extractInnerClass(	lexer * currentLexer, 
								int i, 
								int key, 
								struct file * fileInstance, 
								char * source, 
								int bodyCloseIndex ) {
	

	int bodyOpenIndex 				= lexer_findNextToken( currentLexer, i, "{" );

	char * nextToken				= lexer_getToken( currentLexer, i + 1 );

	char * className;



	if( strcmp( nextToken, "extends" ) == 0 ) {

		int nextKey						= lexer_getKey( currentLexer, i + 1 );

		className 						= text_slice( source, key + 5, ( int ) nextKey - 1 );

		bodyCloseIndex 					= lexer_findBodyCloseIndex( currentLexer, i + 2 );

	} else {

		className 						= text_slice( source, key + 5, bodyOpenIndex - 1 ); 

		bodyCloseIndex 					= lexer_findBodyCloseIndex( currentLexer, i + 1 );

	}


	struct class * classInstance 		= application_getClassByClassName( fileInstance->classes, text_removeWhiteSpaces( className ) );

	file_parseClassBody(	currentLexer,
							i + 1,
							bodyCloseIndex,
							source,
							fileInstance,
							classInstance );


	printf("	}\n\n");

}

char * file_extractFunctionDecleration( lexer * currentLexer, int i,  int key, char * source ) {

	int currentKey					= lexer_getKey( currentLexer, i );

	int previousKey					= lexer_getKey( currentLexer, i - 1 );

	int fromPreviousKey				= ( int ) previousKey + 1;


	char * functionDeclaration 		= text_removeWhiteSpaces( text_slice( source, fromPreviousKey, key - 1 ) );

	return functionDeclaration;

}


void file_extractFunction( lexer * currentLexer, int i, int key, struct file * fileInstance, char * source, int bodyCloseIndex, struct array * classesArray ) {

	struct functionLayout * functionInstance 		= malloc( sizeof( struct functionLayout ) );

	functionInstance->variables						= array_new();

	char * functionSource 							= class_extractBodyFromSource( currentLexer, i, source, bodyCloseIndex );

	char * functionDeclaration 						= file_extractFunctionDecleration( currentLexer, i, key, source );

	struct array * functionDeclarationParts			= text_split( functionDeclaration, " \t" );

	struct array * argumentsArray					= method_getArguments_new( currentLexer, key, i, source, functionInstance->variables );

	int declarationLength 							= array_length( functionDeclarationParts );

	char * functionName 							= ( char * ) array_get( functionDeclarationParts,  declarationLength - 1 );


	

	

	functionInstance->name 						= functionName;

	functionInstance->declarationText			= functionDeclaration;

	functionInstance->bodyOriginal				= functionSource;

	functionInstance->arguments 				= argumentsArray;

	functionInstance->isVariadic				= method_methodIsVaradic( argumentsArray );

	functionInstance->lineNumber				= text_countLineBreaks( source, ( int ) key );

	method_extractVariablesFromArguments( functionInstance->arguments, classesArray, functionInstance->variables );


	array_add( allFunctions, functionInstance );

	array_add( fileInstance->functions, functionInstance ); 

}

char * file_removeSingleLineComment_new( lexer * currentLexer, int i, char * source ) { 

	int nextLineIndex 		= lexer_findNextToken( currentLexer, i, "\n" );

	int key 				= lexer_getKey( currentLexer, i );

	int numberOfCharacters	= nextLineIndex - ( int ) key;

	return text_replaceAt( ( int ) key, nextLineIndex, source, "" );

}

char * file_removeArrayTypeDefinitions( char * source ) {

	lexer * currentLexer		= lexer_new();

	//lexer_setSource( source );

	lexer_tokenize( currentLexer, source, "<");

	lexer_tokenize( currentLexer, source, ">");

	lexer_sortKeys( currentLexer );


	int count 				= lexer_length( currentLexer );

	for (int i = count - 1; i >= 0; --i)
	{

		char * token 		= lexer_getToken( currentLexer, i );

		if ( strcmp( token, "<" ) == 0 ) {


			int closeTypeDefinition = lexer_findNextToken( currentLexer, i, ">" );

			int key 				= lexer_getKey( currentLexer, i );

			int previousKeyIndex 	= text_findFirstCharacterReverse( source, key );

			char * wordBeforeKey	= text_extractWordBeforeKey( source, key );

			if ( strcmp( wordBeforeKey, "array" ) == 0 ) {

				for (int i = key; i < closeTypeDefinition + 1; ++i)
				{
					source[i] =  32;
				}

				printf("\n\n\n 		remove this array declaration:			%s\n\n\n", wordBeforeKey);

			}

			

		}

	}

	return source;

}


char * file_removeSingleLineComments( char * source ) {

	lexer * currentLexer		= lexer_new();

	//lexer_setSource( source );

	lexer_tokenize( currentLexer, source, "//");

	lexer_tokenize( currentLexer, source, "\n");

	lexer_sortKeys( currentLexer );


	int count 				= lexer_length( currentLexer );

	for (int i = count - 1; i >= 0; --i)
	{

		char * token 		= lexer_getToken( currentLexer, i );

		if ( strcmp( token, "//" ) == 0 ) {

			source = file_removeSingleLineComment_new( currentLexer, i, source );

		}

	}

	return source;

}

char * file_replaceMultiLineComment( lexer * currentLexer, int i, char * source ) {

	int key 					= lexer_getKey( currentLexer, i );

	int closeCommentIndex 		= lexer_findNextToken( currentLexer, i, "*/" ) + 2;

	char * comment 				= text_slice( source, key, closeCommentIndex - 1 );

	int numberOfLineBreaks		= text_countLineBreaks( comment, -1 );

	char * replacementText		= malloc( numberOfLineBreaks + 1 );

	replacementText[0] = 0;

	for ( int j = 0; j < numberOfLineBreaks; ++j )
	{

		strcat( replacementText, "\n" );

	}

	//printf("------------- open comment found: %s \n\n --%s-- \n\n %i \n", filename, comment, numberOfLineBreaks);

	return text_replaceAt( ( int ) key, closeCommentIndex , source, replacementText );

}

char * file_removeMultiLineComments( char * source ) {

	lexer * currentLexer		= lexer_new();

	lexer_tokenize( currentLexer, source, "/*" );

	lexer_tokenize( currentLexer, source, "*/" );

	lexer_sortKeys( currentLexer );


	int count 				= lexer_length( currentLexer );


	for (int i = count - 1; i >= 0; --i)
	{

		char * token 		= lexer_getToken( currentLexer, i );

		if ( strcmp( token, "/*" ) == 0 ) {

			source = file_replaceMultiLineComment( currentLexer, i, source );

		}

	}

	return source;

}

void file_removeComments( struct file * fileInstance ) {

	char * filename 		= fileInstance->path;

	char * source			= fileInstance->source;



	//source					= file_removeArrayTypeDefinitions( source );

	source					= file_removeSingleLineComments( source );

	source					= file_removeMultiLineComments( source );


	fileInstance->source 	= source;

}

void file_extractGlobalVariable( lexer * currentLexer, int key, int i, struct file * fileInstance, char * source ) {

	int semicolonIndex					= lexer_findPreviousKeyByToken( currentLexer, i, ";" );

	void * previousToken				= lexer_getToken( currentLexer, i - 1 );

	int previousKey 					= lexer_getKey( currentLexer, i - 1 );


	char * globalDeclaration			= text_removeWhiteSpaces( text_slice( source, semicolonIndex + 1, key ) );

	struct variable * variableInstance 	= variabe_new();



	struct array * ISParts				= text_split( globalDeclaration, "=" );

	char * beforeIS						= array_get( ISParts, 0 );

	struct array * semicolonParts		= text_split( globalDeclaration, ";" );

	char * beforeSemocolon				= array_get( semicolonParts, 0 );


	struct array * defineParts			= text_split( beforeSemocolon, " \t" );

	char * variableName					= array_get( defineParts, array_length( defineParts ) - 1 );



	variableInstance->variableName		= variableName;

	variableInstance->isPointer			= variable_isPointer( defineParts );

	variableInstance->declaration		= globalDeclaration;

	variableInstance->lineNumber		= text_countLineBreaks( source, ( int ) key );

	variableInstance->datatype			= tools_findDatatype( defineParts );


	array_add( fileInstance->globals, variableInstance );

	//printf(" %i		previous token: %s	extract global: %s  pointer: %i \n\n",semicolonIndex, previousToken, globalDeclaration, variableInstance->isPointer);


}

void file_extractClasses( struct file * fileInstance ) {

	printf("Extract classes from file:	'%s' \n\n", fileInstance->filename);

	char * source				= fileInstance->source;

	array * classesArray		= array_new();

	lexer * currentLexer		= lexer_new();


	lexer_getTokens( currentLexer, source );

	lexer_sortKeys( currentLexer );


	int count 				= lexer_length( currentLexer );

	int bodyCloseIndex		= 0;

	int depth				= 0;


	for (int i = count - 1; i >= 0; --i)
	{

		char * token 		= lexer_getToken( currentLexer, i );

		int key 			= lexer_getKey( currentLexer, i );

		if ( strcmp( token, "{" ) == 0 ) {

			depth++;

		}

		if ( strcmp( token, "}" ) == 0 ) {

			depth--;

		}

		if( depth == 0 ) {

			if ( strcmp( token, ";" ) == 0 ) {

				file_extractGlobalVariable( currentLexer, key, i, fileInstance, source );
	
			}

		}

		if ( strcmp( token, "class" ) == 0 ) {

			if( depth == 0 ) {

				file_extractClass( currentLexer, key, i, classesArray, depth, source );

			}

		} 


	}

	fileInstance->classes	= classesArray;

}

void file_extractClass( lexer * currentLexer, int key, int i, struct array * classesArray, int depth, char * source ) {


	char * previousToken			= lexer_getToken( currentLexer, i - 1 );

	char * nextToken				= lexer_getToken( currentLexer, i + 1 );

	int bodyOpenIndex 				= lexer_findNextToken( currentLexer, i, "{" );

	struct class * classInstance 	= class_new();

	classInstance->hasReflection		= false;


	if( i > 0 ) {

		if( strcmp( previousToken, "reflect" ) == 0 ) {

			printf("this class is using reflection\n\n");

			classInstance->hasReflection		= true;


		}

		if( strcmp( previousToken, ">" ) == 0 ) {

			char * templateName			= lexer_getToken( currentLexer, i - 3 );


			if( strcmp( templateName, "template" ) == 0 ) {

				int fromKey					= lexer_getKey( currentLexer, i - 2 ) + 1;

				int toKey					= lexer_getKey( currentLexer, i - 1 ) - 1;

				char * templateArguments	= text_slice( source, fromKey, toKey );


				classInstance->usesTemplate = true;

				classInstance->template		= template_new();

				template_add_arguments( classInstance->template, templateArguments );

				printf("this class has a template:	%s \n\n", templateArguments);

			}
			

			//classInstance->hasReflection		= true;


		}
	}


	if( strcmp( nextToken, "extends" ) == 0 ) {

		int nextKey					= lexer_getKey( currentLexer, i + 1 );


		char * className			= text_slice( source, key + 5, nextKey - 1 );

		classInstance->className	= text_removeWhiteSpaces( className );


		char * extendsText			= text_slice( source, nextKey + 7, bodyOpenIndex - 1 );

		char * extendsTextCopy		= text_copy( extendsText );

		classInstance->extends 		= text_split( extendsTextCopy, "," );

	} else {

		classInstance->extends		= array_new();

		char * className			= text_slice( source, key + 5, bodyOpenIndex - 1 );

		classInstance->className	= text_removeWhiteSpaces( className ); 

	}
	

	classInstance->properties 		= array_new();

	classInstance->methods 			= array_new();

	classInstance->classIndex		= globalClassIndex++;


	printf( "	class %s{}\n", classInstance->className );

	array_add( classesArray, classInstance );

	array_add( allClasses, classInstance );

}


void file_composeFunctionArguments( struct functionLayout * currentFunction, struct text * methodSource, struct text * classHeader ) {

	struct array * arguments = currentFunction->arguments;

	int argumentCount = array_length( arguments );

	for (int j = 0; j < argumentCount; ++j)
	{
		char * argumentText = (char *) array_get( currentFunction->arguments, j );

		text_append( methodSource, argumentText );

		text_append( classHeader, text_copy( argumentText ) );

		if( j != argumentCount-1 ) {

			text_append( methodSource, ", " );

			text_append( classHeader, ", " );

		}

	}

}


void file_composeFunction( struct functionLayout * currentFunction, struct array * sourceArray, struct text * classHeader ) {

	struct codeBundle * code 				= malloc( sizeof( struct codeBundle ) );	

	struct text * methodSource				= text_new( "" );

	text_append( methodSource, currentFunction->declarationText );

	text_append( classHeader, currentFunction->declarationText );


	text_append( methodSource, "( ");

	text_append( classHeader, "( ");


	file_composeFunctionArguments( currentFunction, methodSource, classHeader );


	text_append( classHeader, " );\n\n" );

	text_append( methodSource, " ) {" );

		text_append( methodSource, currentFunction->body );

	text_append( methodSource, "}" );


	code->lineNumber	= currentFunction->lineNumber;

	code->sourceCode	= methodSource->value;

	array_add( sourceArray, code );

}

void file_composeFunctions( struct array * functions, struct array * sourceArray, struct text * classHeader ) {

	int functionCount = array_length( functions );

	for (int i = 0; i < functionCount; ++i)
	{
		struct functionLayout * currentFunction 	= array_get( functions, i );

		file_composeFunction( currentFunction, sourceArray, classHeader );

	}

	int maxLineNumber	= 0;

	int sourceCount = array_length( sourceArray );

	// align undefined line numbers for added function 

	for ( int i = 0; i < sourceCount; ++i )
	{
		struct codeBundle * code 	= array_get( sourceArray, i );

		int afterBodyLineNumber	= code->lineNumber + text_countLineBreaks( code->sourceCode, -1 );

		if( afterBodyLineNumber > maxLineNumber ) {

			maxLineNumber = afterBodyLineNumber;

		}
		
	}

	maxLineNumber += 2;

	for (int i = 0; i < sourceCount; ++i)
	{
		struct codeBundle * code 	= array_get( sourceArray, i );

		if( code->lineNumber == -1 ) {

			code->lineNumber 	= maxLineNumber;

			maxLineNumber		+= text_countLineBreaks( code->sourceCode, -1 );

			maxLineNumber		+= 2;

		}

	}

	maxLineNumber += 12;

}

// this need to be in a separate file

void file_composeConfigInformation( struct array * files, struct application * applicationInstance ) {

	int fileCount 							= array_length( files );

	struct text * configurationHeader 		= text_new( "" );

	struct text * configurationSource 		= text_new( "" ); 


	int classesCount						= array_length( allClasses );


	text_append( configurationHeader, "#ifndef __" );

	text_append( configurationHeader, "classConfiguration\n\n" );

	text_append( configurationHeader, "#define __classConfiguration\n\n" );
	
	text_append( configurationHeader, "#include <stddef.h>\n\n" );





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

		struct file * fileInstance		= array_get( files, i );

		char * path		 					= fileInstance->path;

		char * filename 					= fileInstance->filename;

		if( array_length( fileInstance->classes ) > 0 ) {



			text_append( configurationHeader, "#include <" );

			
			text_append( configurationHeader, path );

			//text_append( configurationHeader, filename );

			text_append( configurationHeader, ".h>\n\n" );

		}

	}





	

	text_append( configurationHeader, "#define TOTAL_CLASS_COUNT " );



	text_append( configurationHeader, text_fromNumber(classesCount) );

	text_append( configurationHeader, "\n\n" );


	text_append( configurationSource, "#include <classConfiguration.h>\n\n" );

	text_append( configurationHeader, "extern char * __ClassNames[TOTAL_CLASS_COUNT];\n");

	text_append( configurationHeader, "extern int __ClassPropertyCount[TOTAL_CLASS_COUNT];\n");

	text_append( configurationHeader, "extern char * __ClassPropertyNames[TOTAL_CLASS_COUNT][30];\n");

	text_append( configurationHeader, "extern int __ClassPropertyOffsets[TOTAL_CLASS_COUNT][30];\n");
	
	text_append( configurationHeader, "extern int __ClassPropertyOffsets[TOTAL_CLASS_COUNT][30];\n");



	text_append( configurationSource, "char * __ClassNames[TOTAL_CLASS_COUNT] 			= { ");


	for (int i = 0; i < classesCount; ++i)
	{
		struct class * classInstance		= array_get( allClasses, i );

		if( i != 0 ) {

			text_append( configurationSource, ", " );

		}


		text_append( configurationSource, "\"" );

		text_append( configurationSource, classInstance->className );

		text_append( configurationSource, "\"" );

	}

	text_append( configurationSource, " };\n\n" );






	text_append( configurationSource, "int __ClassMethodCount[TOTAL_CLASS_COUNT] 	= { ");

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

		struct class * classInstance		= array_get( allClasses, i );

		if( i != 0 ) {

			text_append( configurationSource, ", " );

		}

		text_append( configurationSource, text_fromNumber( array_length( classInstance->methods ) ) );

	}

	text_append( configurationSource, " };\n\n" );















	text_append( configurationSource, "int __ClassPropertyCount[TOTAL_CLASS_COUNT] 	= { ");

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

		struct class * classInstance		= array_get( allClasses, i );

		if( i != 0 ) {

			text_append( configurationSource, ", " );

		}

		text_append( configurationSource, text_fromNumber( array_length( classInstance->properties ) ) );

	}

	text_append( configurationSource, " };\n\n" );




	text_append( configurationSource, "char * __ClassPropertyNames[TOTAL_CLASS_COUNT][30] 	= {\n");

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

		struct class * classInstance		= array_get( allClasses, i );

		if( i != 0 ) {

			text_append( configurationSource, ", \n" );

		}

		struct array * properties	= classInstance->properties;

		int propertyCount			= array_length( properties );

		text_append( configurationSource,  "\t\t\t\t\t\t\t\t\t\t\t\t\t\t{");

		if( propertyCount == 0 ) {

			text_append( configurationSource, " " );

		}

		for (int j = 0; j < propertyCount; ++j)
		{
			struct property * currentProperty	= array_get( properties, j );

			if( j != 0 ) {

				text_append( configurationSource, ", " );

			}

			text_append( configurationSource, " \"" );

			text_append( configurationSource, currentProperty->propertyName );

			text_append( configurationSource, "\" " );
			
		}

		text_append( configurationSource,  "}");

	}

	text_append( configurationSource, "\n\t\t\t\t\t\t\t\t\t\t\t\t\t};\n\n" );




	text_append( configurationSource, "char * __ClassMethodNames[TOTAL_CLASS_COUNT][30] 	= {\n");

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

		struct class * classInstance		= array_get( allClasses, i );

		if( i != 0 ) {

			text_append( configurationSource, ", \n" );

		}

		struct array * methods	= classInstance->methods;

		int methodCount			= array_length( methods );

		text_append( configurationSource,  "\t\t\t\t\t\t\t\t\t\t\t\t\t\t{");

		if( methodCount == 0 ) {

			text_append( configurationSource, " " );

		}

		for (int j = 0; j < methodCount; ++j)
		{
			struct method * currentMethod	= array_get( methods, j );

			if( j != 0 ) {

				text_append( configurationSource, ", " );

			}

			text_append( configurationSource, " \"" );

			text_append( configurationSource, currentMethod->methodName );

			text_append( configurationSource, "\" " );
			
		}

		text_append( configurationSource,  "}");

	}

	text_append( configurationSource, "\n\t\t\t\t\t\t\t\t\t\t\t\t\t};\n\n" );







	text_append( configurationSource, "int __ClassPropertyOffsets[TOTAL_CLASS_COUNT][30] 	= {\n");

	int index = 0;

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

		struct class * classInstance		= array_get( allClasses, i );

		if( classInstance->usesTemplate ) {

			continue;

		}

		



		char * className					= classInstance->className;

		if( index != 0 ) {

			text_append( configurationSource, ", \n" );

		}

		index++;

		struct array * properties	= classInstance->properties;

		int propertyCount			= array_length( properties );

		text_append( configurationSource,  "\t\t\t\t\t\t\t\t\t\t\t\t\t\t{");

		if( propertyCount == 0 ) {

			text_append( configurationSource, " " );

		}

		for (int j = 0; j < propertyCount; ++j)
		{
			struct property * currentProperty	= array_get( properties, j );

			if( strcmp( currentProperty->type, "function" ) == 0 ) {

				continue;

			}

			if( j != 0 ) {

				text_append( configurationSource, ", " );

			}

			text_append( configurationSource, " offsetof(  ");

			text_append( configurationSource, className);

			text_append( configurationSource, ", " );

			text_append( configurationSource, currentProperty->propertyName );

			text_append( configurationSource, " )" );

				

			

			text_append( configurationSource, " " );
			
		}

		text_append( configurationSource,  "}");

	}

	text_append( configurationSource, "\n\t\t\t\t\t\t\t\t\t\t\t\t\t};\n\n" );



	text_append( configurationSource, "int __ClassPropertyDatatypeIndices[TOTAL_CLASS_COUNT][30] 	= {\n");

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

		struct class * classInstance		= array_get( allClasses, i );

		char * className					= classInstance->className;

		if( i != 0 ) {

			text_append( configurationSource, ", \n" );

		}

		struct array * properties	= classInstance->properties;

		int propertyCount			= array_length( properties );

		text_append( configurationSource,  "\t\t\t\t\t\t\t\t\t\t\t\t\t\t{");

		if( propertyCount == 0 ) {

			text_append( configurationSource, " " );

		}

		for (int j = 0; j < propertyCount; ++j)
		{
			struct property * currentProperty	= array_get( properties, j );

			if( j != 0 ) {

				text_append( configurationSource, ", " );

			}

			//text_append( configurationSource, "\"");

			/*
			*	char	: 		-3
			*	char *	:		-2
			*	short	:		-4
			*	int 	: 		-5
			*	long	: 		-6
			*/		

			if( strcmp( currentProperty->datatype, "char" ) == 0 ) {

				if( currentProperty->isPointer == 1 ) {

					text_append( configurationSource, text_fromNumber( -3 ) );

				} else {

					text_append( configurationSource, text_fromNumber( -2 ) );

				}
				

			} else if( strcmp( currentProperty->datatype, "short" ) == 0 ) {

				text_append( configurationSource, text_fromNumber( -4 ) );

			} else if( strcmp( currentProperty->datatype, "int" ) == 0 ) {

				text_append( configurationSource, text_fromNumber( -5 ) );

			} else if( strcmp( currentProperty->datatype, "long" ) == 0 ) {

				text_append( configurationSource, text_fromNumber( -6 ) );

			} else {


				struct class * datatypeClass = application_getClassByClassName( allClasses, currentProperty->datatype );

				if( datatypeClass != NULL ) {

					//printf("-------------------------- classIndex:		%i\n" ,datatypeClass->classIndex);

					text_append( configurationSource, text_fromNumber( datatypeClass->classIndex ) );

				} else {

					text_append( configurationSource, text_fromNumber( 1 ) );

				}


				//text_append( configurationSource, currentProperty->datatype );//text_fromNumber( datatypeClass->classIndex ) );

			}
			

			//text_append( configurationSource, "\"" );

			//text_append( configurationSource, currentProperty->propertyName );

			//text_append( configurationSource, " )" );

				

			

			text_append( configurationSource, " " );
			
		}

		text_append( configurationSource,  "}");

	}

	text_append( configurationSource, "\n\t\t\t\t\t\t\t\t\t\t\t\t\t};\n\n" );



	text_append( configurationSource, "void getArrayByClassIndex( int size, void * * voidArray, int * structByteSize, int classIndex ) {\n\n" );

	//text_append( configurationSource, "	struct user * array;\n\n" );

	text_append( configurationSource, "	switch( classIndex ) {\n\n" );



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

		struct class * classInstance		= array_get( allClasses, i );


		if( classInstance->usesTemplate ) {

			continue;

		}


		char * className						= classInstance->className;

		if( strcmp( className, "char") == 0 ) {

			continue;

		}

		if( strcmp( className, "int") == 0 ) {

			continue;
			
		}

		int classIndex							= classInstance->classIndex;

		text_append( configurationSource, "		case " );

		text_append( configurationSource, text_fromNumber( classIndex )  );

		text_append( configurationSource, ":\n\n" );



		text_append( configurationSource, "			voidArray 				= ( void ** ) ( struct " );

		text_append( configurationSource, className );

		text_append( configurationSource, " * ) malloc( sizeof( struct " );	

		text_append( configurationSource, className );

		text_append( configurationSource, " ) * size );\n\n" ); 



		text_append( configurationSource, "			*structByteSize			= sizeof( struct " ); 

		text_append( configurationSource, className );

		text_append( configurationSource, " );\n\n" ); 



		text_append( configurationSource, "		break;\n\n" );

	}

	text_append( configurationSource, "	}\n\n" );

	//text_append( configurationSource, "	voidArray				= ( void ** ) array;\n\n" );
	
	
	text_append( configurationSource, "}\n\n" );




	text_append( configurationSource, "void callMethodOfClass( int classIndex, int methodIndex, void * object ) {\n\n" );

	//text_append( configurationSource, "	struct user * array;\n\n" );

	text_append( configurationSource, "	switch( classIndex ) {\n\n" );



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

		struct class * classInstance		= array_get( allClasses, i );

		if( classInstance->usesTemplate ) {

			continue;

		}


		char * className						= classInstance->className;

		if( strcmp( className, "char") == 0 ) {

			continue;

		}

		if( strcmp( className, "int") == 0 ) {

			continue;
			
		}

		int classIndex							= classInstance->classIndex;

		text_append( configurationSource, "		case " );

		text_append( configurationSource, text_fromNumber( classIndex )  );

		text_append( configurationSource, ":\n\n" );




		text_append( configurationSource, "			switch( methodIndex ) {\n\n" );


		array * methods		= classInstance->methods;

		int methodsCount	= array_length( methods );


		if( methodsCount > 0 ) {

			for (int methodIndex = 0; methodIndex < methodsCount; ++methodIndex)
			{
				
				struct method * currentMethod	= array_get( methods, methodIndex );


				if( array_length( currentMethod->arguments ) == 1 ) {
				
					text_append( configurationSource, "				case " );

					text_append( configurationSource, text_fromNumber( methodIndex ) );

					text_append( configurationSource, ":\n\n" );



					text_append( configurationSource, "					" );

					text_append( configurationSource, className );

					text_append( configurationSource, "_" );

					text_append( configurationSource, currentMethod->methodName );

					text_append( configurationSource, "( object );\n\n" );
					
					text_append( configurationSource, "				break;\n\n " );

				}

			}

		}


		text_append( configurationSource, "			}\n\n" );





		text_append( configurationSource, "		break;\n\n" );

	}

	text_append( configurationSource, "	}\n\n" );

	//text_append( configurationSource, "	voidArray				= ( void ** ) array;\n\n" );
	
	
	text_append( configurationSource, "}\n\n" );

















/*
	int __ClassPropertyCount[4] = 
{
	4, 6
};
*/

	//text_append( configurationHeader, "int");


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

		struct file * fileInstance		= array_get( files, i );

		char * filename 				= fileInstance->filename;

		char * source					= fileInstance->source;

		struct array * classesArray		= fileInstance->classes;

	}


	

	char * header		= fileSystem_readFile( "../source/configuration.h" );


	text_append( configurationHeader, header );

	text_append( configurationHeader, "#endif\n" );


	char * filePath			= file_composePath( applicationInstance->output, "classConfiguration", "h" );


	fileSystem_writeFile( filePath, configurationHeader->value );



	char * functions		= fileSystem_readFile( "../source/configuration.c" );


	filePath					= file_composePath( applicationInstance->output, "classConfiguration", "c" );


	text_append( configurationSource, functions );
	


	fileSystem_writeFile( filePath, configurationSource->value );

}



// end

char * file_composePath( char * path, char * filename, char * extension ) {

	char * filePath		 = malloc(1000);

	filePath[0] = 0;

	strcat( filePath, path );

	strcat( filePath, filename );

	strcat( filePath, "." );

	strcat( filePath, extension );

	return filePath;

}


void file_composeNewPointerFunction( struct text * finalSourceCode, int hasConstructor, struct array * constructorArguments, struct class * classInstance ) {

	//char * contructorArgumentsText			= text_join( constructorArguments, "," );

	text_append( finalSourceCode, classInstance->className );

	text_append( finalSourceCode, " * " );

	text_append( finalSourceCode, classInstance->className );

	text_append( finalSourceCode, "_newPointer(" );

		//text_append( finalSourceCode, contructorArgumentsText );

	int count	= array_length( constructorArguments );

	for (int i = 1; i < count; ++i)
	{
		char * argument = text_removeWhiteSpaces( array_get( constructorArguments, i ) );

		if( i > 1 ) {

			text_append( finalSourceCode, ", " );
			
		}

		text_append( finalSourceCode, argument );
		
	}

	text_append( finalSourceCode, ") {\n\n" );

	text_append( finalSourceCode, "	struct " );

	text_append( finalSourceCode, classInstance->className );

	text_append( finalSourceCode, " * pointer = malloc( sizeof ( struct " );

	text_append( finalSourceCode, classInstance->className );

	text_append( finalSourceCode, " ) );\n\n" );


	file_composePropertieInitiations( finalSourceCode, 1, classInstance );

	if( hasConstructor == 1 ) {

		file_composeConstructorCall( finalSourceCode, classInstance->className, constructorArguments, -1 );

	}

	text_append( finalSourceCode, "	return pointer;\n\n" );

	text_append( finalSourceCode, "}\n\n" );

}

void file_composeConstructorCall( struct text * finalSourceCode, char * className, struct array * constructorArguments, int usePointer ) {

	text_append( finalSourceCode, "	" );

	text_append( finalSourceCode, className );

	if( usePointer == 1 ) {

		text_append( finalSourceCode, "_constructor( &instance"  );

	} else {

		text_append( finalSourceCode, "_constructor( pointer " );

	}

	int argumentCount = array_length( constructorArguments );

	for (int j = 1; j < argumentCount; ++j)
	{
		char * argumentText = ( char * ) array_get( constructorArguments, j );

		struct array * argumentParts 	= text_split( argumentText, " \t" );

		text_append( finalSourceCode, ", " );

		text_append( finalSourceCode, array_get( argumentParts, array_length( argumentParts ) - 1  ) );

	}

	text_append( finalSourceCode, ");\n\n" );

}


void file_composePropertieInitiations( struct text * finalSourceCode,  int usePointers, struct class * classInstance ) {


	char * className					= classInstance->className;

	struct array * properties 			= classInstance->properties;

	int classIndex						= classInstance->classIndex;

	int propertyLength					= array_length( properties );


	if( classInstance->hasReflection == true ) {

		if( strcmp( className, "Hints" ) != 0 ) {

			if( usePointers == 1 ) {

				text_append( finalSourceCode, "	pointer->__classIndex = " );

			} else {

				text_append( finalSourceCode, "	instance.__classIndex = " );

			}

			text_append( finalSourceCode, text_fromNumber( classIndex ) );

			text_append( finalSourceCode, ";\n\n" );

		}

	}


	for (int i = 0; i < propertyLength; ++i)
	{
		struct property * currentProperty = array_get( properties, i );

		if( currentProperty->hasValue == 1 ) {

			char * propertyName 	= currentProperty->propertyName;

			char * propertyValue	= currentProperty->value;

			if( usePointers == 1 ) {

				text_append( finalSourceCode, "	pointer->" );

			} else {

				text_append( finalSourceCode, "	instance." );

			}
			
			text_append( finalSourceCode, propertyName );

			text_append( finalSourceCode, " = " );

			text_append( finalSourceCode, currentProperty->value );

			text_append( finalSourceCode, ";\n\n" );

		}

	}

}

void file_composeNewFunction( struct text * finalSourceCode, int hasConstructor, struct array * constructorArguments, struct class * classInstance ) {


	array * argumentsWithoutFirst				= array_new();

	int argumentCount 										= array_length( constructorArguments );

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

		char * constructorArgument = array_get( constructorArguments, i );

		array_add( argumentsWithoutFirst, constructorArgument );

	}


	char * contructorArgumentsText			= text_join( argumentsWithoutFirst, ", " );


	text_append( finalSourceCode, classInstance->className );

	text_append( finalSourceCode, " " );

	text_append( finalSourceCode, classInstance->className );

	text_append( finalSourceCode, "_new(" );

	int count	= array_length( constructorArguments );

	for (int i = 1; i < count; ++i)
	{
		char * argument = text_removeWhiteSpaces( array_get( constructorArguments, i ) );

		if( i > 1 ) {

			text_append( finalSourceCode, ", " );
			
		}

		text_append( finalSourceCode, argument );
		
	}
	text_append( finalSourceCode, ") {\n\n" );

	text_append( finalSourceCode, "	" );

	text_append( finalSourceCode, classInstance->className );

	text_append( finalSourceCode, " instance;\n\n" );

	file_composePropertieInitiations( finalSourceCode, -1,  classInstance );

	if( hasConstructor == 1 ) {

		file_composeConstructorCall( finalSourceCode, classInstance->className, constructorArguments, 1 );

	}

	text_append( finalSourceCode, "	return instance;\n\n" );

	text_append( finalSourceCode, "}\n\n" );

}


void file_composeNewFunctions( struct text * finalSourceCode, struct class * classInstance, int hasConstructor, struct array * constructorArguments ) {

	char * className					= classInstance->className;

	struct array * properties 			= classInstance->properties;

	int classIndex						= classInstance->classIndex;


	file_composeNewFunction( finalSourceCode, hasConstructor, constructorArguments, classInstance );

	file_composeNewPointerFunction( finalSourceCode, hasConstructor, constructorArguments, classInstance );

}


void file_composeNewHeaderDeclerations( struct text * classHeader, char * className, struct array * contructorArguments ) {

	text_append( classHeader, className );

	text_append( classHeader, " " );

	text_append( classHeader, className );

	text_append( classHeader, "_new( " );

	int count = array_length( contructorArguments );

	for (int i = 1; i < count; ++i)
	{
		char * argument = text_removeWhiteSpaces( array_get( contructorArguments, i ) );

		if( i > 1 ) {

			text_append( classHeader, ", " );
			
		}

		text_append( classHeader, argument );
		
	}

	//text_append( classHeader, ( contructorArgumentsText ) );

	text_append( classHeader, " );\n\n" );

	text_append( classHeader, className );

	text_append( classHeader, " * " );

	text_append( classHeader, className );

	text_append( classHeader, "_newPointer( " );

	for (int i = 1; i < count; ++i)
	{
		char * argument = text_removeWhiteSpaces( array_get( contructorArguments, i ) );

		if( i > 1 ) {

			text_append( classHeader, ", " );
			
		}

		text_append( classHeader, argument );
		
	}

	//text_append( classHeader, text_copy( contructorArgumentsText ) );

	text_append( classHeader, " );\n\n" );

}

struct array * file_getConstructorArguments( struct class * classInstance, int * hasConstructor ) {

	struct array * constructorArguments 	= array_new();

	int length								= array_length( classInstance->methods );

	for ( int j = 0; j < length; ++j )
	{
		struct method * currentMethod 		= ( struct method * ) array_get( classInstance->methods, j );

		char * methodName					= currentMethod->methodName;

		if( strcmp( methodName, "constructor" ) == 0 ) {

			constructorArguments 			= currentMethod->arguments;

			*hasConstructor					= 1;

		}

	}

	return constructorArguments;

}

void file_composeClass( struct class * classInstance, struct text * classHeader, struct text * finalSourceCode ) {

	char * className 								= classInstance->className;

	int hasConstructor 							= -1;

	int length										= array_length( classInstance->methods );

	struct array * constructorArguments		= file_getConstructorArguments( classInstance, &hasConstructor );

	//char * contructorArgumentsText			= text_join( constructorArguments, "," );

	//if( array_length( constructorArguments ) == 0 ) {

		//contructorArgumentsText = " ";

	//}


	if( strcmp( className, "char" ) == 0 || strcmp( className, "int" ) == 0 ) {

		return;

	}

	file_composeNewHeaderDeclerations( classHeader, className, constructorArguments );

	file_composeNewFunctions( finalSourceCode, classInstance, hasConstructor, constructorArguments );

}

void file_addLineBreaks( struct text * finalSourceCode, struct array * sourceArray ) {

	int count	= array_length( sourceArray );

	for ( int i = 0; i < count; ++i )
	{
		struct codeBundle * code 	= array_get( sourceArray, i );

		int currentLineBreaks 		= text_countLineBreaks( finalSourceCode->value, -1 );

		int addingLinebreaks		= code->lineNumber - currentLineBreaks;

		//printf("adding linebreaks:  %i\n", addingLinebreaks);

		for (int j = 0; j < addingLinebreaks; ++j)
		{
			text_append( finalSourceCode, "\n" );
		}
		
		text_append( finalSourceCode, code->sourceCode );

	}

	text_append( finalSourceCode, "\n\n" );

}


void file_composeSourceHeader( struct text * finalSourceCode, char * filename ) {

	text_append( finalSourceCode, "/* \n * This file is automaticaly generated, Please dont edit this file! \n */\n" );

	text_append( finalSourceCode, "#include <" );

	text_append( finalSourceCode, filename );

	text_append( finalSourceCode, ".h> \n\n" );

}

void file_writeAll( struct array * sourceArray, struct text * classHeader, char * filename, array * classesArray, array * globals, char * relativePath, struct application * applicationInstance  ) {


	struct text * finalSourceCode		= text_new( "" );

	int globalCount						= array_length( globals );

	for (int i = 0; i < globalCount; ++i)
	{
		
		struct variable * variableInstance			= array_get( globals, i );

		struct array * sourceParts						= text_split( text_copy( variableInstance->declaration ), " " );

		struct text * declarationWithoutExtern		= text_new( "" );

		int sourcePartsLength							= array_length( sourceParts );

		for (int j = 0; j < sourcePartsLength; ++j)
		{

			char * sourceCodePart	= text_removeWhiteSpaces( ( char * ) array_get( sourceParts, j ) );

			if( strcmp( sourceCodePart, "extern" ) != 0 ) {

				text_append( declarationWithoutExtern, sourceCodePart );

				text_append( declarationWithoutExtern, " " );

			}
			
		}

		struct codeBundle * sourceCodeBundle 	= malloc( sizeof( struct codeBundle ) );

		sourceCodeBundle->sourceCode			= declarationWithoutExtern->value;

		sourceCodeBundle->lineNumber			= variableInstance->lineNumber;

		array_add( sourceArray, sourceCodeBundle );

		//struct text * declarationBeforeIS				= text_new();


		for (int j = 0; j < sourcePartsLength; ++j)
		{

			char * sourceCodePart	= text_removeWhiteSpaces( ( char * ) array_get( sourceParts, j ) );

			if( strcmp( sourceCodePart, "=" ) == 0 ) { 

				text_append( classHeader, ";" );

				break;

			}

			text_append( classHeader, sourceCodePart );

			text_append( classHeader, " " );

		}

		text_append( classHeader, "\n\n" );

	}
	

	method_sortLineNumbers( sourceArray );

	file_composeSourceHeader( finalSourceCode, filename );

	file_addLineBreaks( finalSourceCode, sourceArray );


	int classesCount = array_length( classesArray );

	for (int i = 0; i < classesCount; ++i)
	{
		
		struct class * classInstance 			= array_get( classesArray, i );

		if( i == 0 ) {

			if( classInstance->usesTemplate ) {

				continue;

			}

		}

		file_composeClass( classInstance, classHeader, finalSourceCode );

	}

	text_append( classHeader, "#endif\n" );


	for (int i = 0; i < classesCount; ++i)
	{
		
		struct class * classInstance 			= array_get( classesArray, i );

		char * className						= classInstance->className;

		if( strcmp( className, "char" ) != 0 && strcmp( className, "int" ) != 0 && strcmp( className, "void" ) != 0 ) {

			class_composeTypedefStruct( classInstance, classHeader );

		}


	}


	



	//char * path				= "../application/target/";

	char * filePath			= file_composePath( applicationInstance->output, text_copy( relativePath ), "c" );

	//printf("relativePath:		'%s'\n", text_copy( filePath ));
	
	fileSystem_ensureDirectory( text_copy( filePath ) );

	fileSystem_writeFile( filePath, finalSourceCode->value );

	printf("			writing source file: %s\n", filePath);

	char * headerFilePath	= file_composePath( applicationInstance->output, text_copy(  relativePath ), "h" );

	
	printf("			writing header file: %s\n\n", headerFilePath);
	
	//classHeader->value[classHeader->length] = 0;
	fileSystem_writeFile( headerFilePath, text_copy( classHeader->value ) );

	text_free( classHeader );


}


void file_parseFunctions( struct file * fileInstance, array * files ) {

	struct array * functions = fileInstance->functions;

	int functionsCount = array_length( functions );

	for (int i = 0; i < functionsCount; ++i)
	{
		
		struct functionLayout * functionInstance 	= array_get( functions, i );

		printf("			%s() {\n\n", functionInstance->name);


		int includeCount		= array_length( fileInstance->includes );

		for ( int k = 0; k < includeCount; ++k )
		{
			
			struct include * includeInstance	= array_get( fileInstance->includes, k );

			char * currentInclude	= includeInstance->path;

			char * includeFileName	= text_removeSlashFromStart( file_getFileNameFromInclude( currentInclude ) );

			struct file * includedFile 	= file_getFileByFileName( files, includeFileName );

			if( includedFile != NULL ) {

				//printf("			??	%s.c \n\n", includedFile->filename);

				file_addVariablesFromFile( includedFile, functionInstance->variables );



			}

		}

		

		int globalCount			= array_length( fileInstance->globals );

		for (int k = 0; k < globalCount; ++k)
		{
			
			struct variable * globalVariableInstance		= array_get( fileInstance->globals, k );

			array_add( functionInstance->variables, globalVariableInstance );

		}



		functionInstance->body						= method_parse( functionInstance->bodyOriginal, functionInstance->variables, fileInstance->functions );

		printf("			}\n\n");

	}

}

void file_parseMethods( struct file * fileInstance, array * files ) {

	struct array * fileClasses = fileInstance->classes;

	int classesCount = array_length( fileClasses );

	for (int i = 0; i < classesCount; ++i)
	{
		struct class * classInstance = array_get( fileClasses, i );

		printf("		class %s{\n\n", classInstance->className );

		struct array * methods 		= classInstance->methods;

		int methodsCount			= array_length( methods );

		for (int j = 0; j < methodsCount; ++j)
		{
			
			struct method * methodInstance 	= array_get( methods, j );

			printf("			%s() {\n\n", methodInstance->methodName);

			int includeCount		= array_length( fileInstance->includes );

			for ( int k = 0; k < includeCount; ++k )
			{
				
				struct include * includeInstance	= array_get( fileInstance->includes, k );

				char * currentInclude			= includeInstance->path;

				char * includeFileName			= text_removeSlashFromStart( file_getFileNameFromInclude( currentInclude ) );

				struct file * includedFile 		=  file_getFileByFileName( files, includeFileName );

				if( includedFile != NULL ) {

					//printf("				%s.c \n\n", includedFile->filename);

					file_addVariablesFromFile( includedFile, methodInstance->variables );

				}

			}

			printf("\n\n");

			file_addVariablesFromFile( fileInstance, methodInstance->variables );


			

			//methodInstance->body 				= methodInstance->bodyOriginal;

			

			//if( !classInstance->usesTemplate ) {



				methodInstance->body 			= method_parse( methodInstance->bodyOriginal, methodInstance->variables, fileInstance->functions );

			//}

			printf("			}\n\n");

		}

		printf("		}\n\n"  );

	}

}

void file_addVariablesFromFile( struct file * fileInstance, struct array * variables ) {	

	int globalCount			= array_length( fileInstance->globals );

	//printf("add variables from file %i\n\n\n", globalCount);

	for (int k = 0; k < globalCount; ++k)
	{
		
		struct variable * globalVariableInstance		= array_get( fileInstance->globals, k );

		//printf("				- Adding variable from file: '%s' \n", globalVariableInstance->variableName );

		array_add( variables, globalVariableInstance );

	}

}

char * file_getBaseNameFromFileName( char * filename ) {

	struct array * fileParts 		= text_split( filename, "." );

	return array_get( fileParts, 0 );

}

char * file_getPathFrom( char * filename ) {

	struct array * fileParts 		= text_split( filename, "." );

	return array_get( fileParts, 0 );

}


int libcFileCount				= 293;


char * libcFileNames[293] 	= {"stdlib","stdlib","math","time","time","math","assert","math","math","stdlib","stdlib","stdlib","stdlib","nwchar","stdlib","nl_types","nl_types","nl_types","math","stdio","time","math","math","time","time","time","time","time","time","stdlib","math","io","math","stdlib","math","math","stdio","stdio","stdio","stdio","stdio","stdio","stdio","stdio","nwchar","nwchar","stdio","math","math","stdio","stdio","stdio","stdio","stdio","stdio","stdio","stdlib","stdio","math","stdio","stdio","stdio","stdio","nwchar","nwchar","stdio","nwchar","math","stdio","stdio","stdlib","stdio","nwchar","wchar","time","time","time","time","math","ctype","ctype","ctype","ctype","ctype","ctype","ctype","ctype","ctype","ctype","ctype","ctype","wctype","wctype","wctype","wctype","wctype","wctype","wctype","wctype","wctype","wctype","wctype","wctype","wctype","wctype","math","math","math","stdlib","math","stdlib","locale","time","time","time","time","math","math","setjmp","stdlib","stdlib","wchar","wchar","wchar","wchar","stdlib","stdlib","string","string","string","string","string","time","time","math","math","math","math","math","langinfo","stdio","math","stdio","stdio","stdio","stdlib","stdio","nwchar","wchar","stdlib","math","math","math","math","math","math","math","math","math","signal","stdlib","stdlib","stdlib","regex","regex","regex","regex","stdio","stdio","stdio","stdio","stdio","setjmp","locale","stdio","signal","math","math","stdio","stdio","math","stdlib","stdio","strings","string","string","string","string","string","string","string","wchar","time","string","strings","string","string","string","string","time","string","string","string","stdlib","stdlib","stdlib","stdlib","stdlib","string","string","stdlib","stdlib","stdlib","string","wchar","wchar","stdlib","math","math","time","time","stdio","stdio","ctype","ctype","ctype","wctype","wctype","wctype","stdio","stdio","stdarg","stdarg","stdarg","stdarg","stdio stdarg","stdio stdarg ","nwchar","stdio stdarg ","stdio stdarg","stdio stdarg ","stdio stdarg","stdio","stdio stdarg ","nwchar","stdio wchar ","nwchar","stdio wchar ","wchar","wchar","wchar","wchar","wchar","wchar","wchar","wchar","wchar","locale","wchar","wchar","wchar","wchar","wchar","wchar","wchar","wchar","wchar","wchar","wchar","wchar","wchar","wchar","wchar","wchar","wchar","stdlib","wchar","wchar","nwchar","stdlib","wctype","wchar","wchar","wchar","wchar","wchar","wchar","wchar","wchar","wchar","math","math","math"};


int file_isLibCFileName( char * baseName ) {

	for (int i = 0; i < 293; ++i)
	{
		
		char * libcFileName	= libcFileNames[i] ;

		char * libcBaseName	= libcFileName;

		if( strcmp( baseName, libcBaseName ) == 0 ) {

			//printf("skip libc file:	%s\n\n", libcBaseName);

			return 1.0;

		}

	}

	return 0;

}



int file_hasLoadedFileName( char * fileName, struct array * loadedFileNames ) {

	int loadedFileNamesCount		= array_length( loadedFileNames );

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

		char * currentLoadedFileName = array_get( loadedFileNames, i );

		if ( strcmp( currentLoadedFileName, fileName ) == 0 )
		{
			
			return 1;

		}

	}

	return 0;

}


char * file_getFileNameFromInclude( char * include ) {

	int openIndex				= text_indexOff( include, "<", -1 );

	int closeIndex				= -1;

	if( openIndex > 0 ) {

		closeIndex					= text_indexOff( include, ">", -1 );

	} else {

		openIndex					= text_indexOff( include, "\"", -1 );

		closeIndex					= text_indexOff( include, "\"", openIndex + 1 );

	}

	char * fileName					= text_slice( include, openIndex + 1, closeIndex - 1 );

	struct array * fileNameParts		= text_split( text_copy( fileName ), "." );


	return array_get( fileNameParts, 0 );

}




struct file * file_getFileByFileName( struct array * files, char * includeFileName ) {

	int fileCount 			= array_length( files );

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

		struct file * fileInstance		= array_get( files, i );

		//printf("searching for file: %s \n\n",  includeFileName);

		if( strcmp( fileInstance->filename, includeFileName ) == 0 ) {

			return fileInstance;

		}

	}

	return NULL;

}


char * file_extractInclude( struct file * fileInstance, char * source, lexer * currentLexer, int key, int i ) {

	int nextKey					= lexer_getKey( currentLexer, i + 2 );

	int keyAfterWord			= text_extractIndexAfterWord( source, key + 8 );

	char * includeFileName		= text_slice( source, key, keyAfterWord + 2);


	struct include * includeInstance 	= include_new();

	includeInstance->path				= includeFileName;

	includeInstance->enabled			= true;

	array_add( fileInstance->includes, includeInstance );

//	printf("Add include:	%s\n", includeInstance->path);

	int numberOfCharacters		= ( keyAfterWord + 2 ) - key;


	struct text * includeReplacement 		= text_new( "" );

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

		text_append( includeReplacement, " " );

	}

	return text_replaceAt( key, keyAfterWord + 3, source, includeReplacement->value );

}

char * file_eraseDefine( char * source, int key, int lineBreakIndex ) {

	for (int i = key; i < lineBreakIndex; ++i)
	{

		source[i] = ( char ) 32;

	}

	return source;

}

char * file_extractDefine( struct file * fileInstance, char * source, int key, int i ) {

	int lineBreakIndex			= text_findNextLineBreak( source, key );

	char * macro				= text_slice( source, key, lineBreakIndex );

	int numberOfCharacters		= ( lineBreakIndex + 2 ) - key;

	array_add( fileInstance->macros, macro );


	source						= file_eraseDefine( source, key, lineBreakIndex );

	return source;

}


void file_extractMacros( struct file * fileInstance ) {

	char * source				= fileInstance->source;


	fileInstance->includes		= array_new();

	fileInstance->globals		= array_new();

	fileInstance->macros		= array_new();



	lexer * currentLexer		= lexer_new();

	//printf("Source:		%s\n", source);


	lexer_getTokens( currentLexer, source );

	lexer_sortKeys( currentLexer );


	int count 				= lexer_length( currentLexer );

	int bodyCloseIndex		= -1;

	int depth				= 0;


	for (int i = count - 1; i >= 0; --i)
	{

		char * token 		= lexer_getToken( currentLexer, i );

		int key 			= lexer_getKey( currentLexer, i );

		//printf("Token:	%s\n", token);

		if ( strcmp( token, "{" ) == 0 ) {

			depth++;

		}

		if ( strcmp( token, "}" ) == 0 ) {

			depth--;

		}

		if( depth == 0 ) {

			if ( strcmp( token, "#" ) == 0 ) {

				// #macroname

				int keyAfterMethod 		= text_extractIndexAfterWord( source, key );

				char * macroName		= text_removeWhiteSpaces( text_slice( source, (int) key +1 ,keyAfterMethod - 1) );


				//printf( "%s: 		%i:", token, (int)key );

				//printf("macro:		%s \n", macroName);



				if ( strcmp( macroName, "include" ) == 0 ) {

					source = file_extractInclude( fileInstance, source, currentLexer, key, i );

				}

				if ( strcmp( macroName, "define" ) == 0 ) {

					source = file_extractDefine( fileInstance, source, key, i );

				}

			} 

		}

	}


	fileInstance->source = source;

}


char * file_getSource( char * filename ) {

	char sourceFilePath[200] = "";

	strcat( sourceFilePath, "../application/source/" );

	strcat( sourceFilePath, filename);

	strcat( sourceFilePath, ".c" );

	char * source 	= fileSystem_readFile( sourceFilePath );

	return source;

}

char * file_removeExtensionFromFileName( char * path ) {
/*
	struct array * fileParts 		= text_split( text_copy( path ), "." );

	int count		= array_length( fileParts );

	if( count > 1 ) {

		array_delete( fileParts, count-1 );

	}
*/

	char * pathWithoutExtension	= "";

	char * base = basename( text_copy( path  ) );

	char * dir  = dirname( text_copy( path  ) );
		

	

	pathWithoutExtension = text_concatenate( pathWithoutExtension, dir );

	pathWithoutExtension = text_concatenate( pathWithoutExtension, "/" );

	pathWithoutExtension = text_concatenate( pathWithoutExtension, base );

	if( pathWithoutExtension[0] == '.' && pathWithoutExtension[1] == '/' ) {

		// shift pointer
		pathWithoutExtension += 2;

	}

	int count = strlen( pathWithoutExtension );

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

		if( pathWithoutExtension[count - i ] == 46 ) {

			pathWithoutExtension[ count - i ] = 0;

			break;

		}

		if( pathWithoutExtension[count - i ] == 47 ) {

			break;

		}

	}

	return pathWithoutExtension;

}


char * file_getFileNameFromIncludeFixed( char * include ) {

	int openIndex				= text_indexOff( include, "<", -1 );

	int closeIndex				= -1;

	if( openIndex > 0 ) {

		closeIndex					= text_indexOff( include, ">", -1 );

	} else {

		openIndex					= text_indexOff( include, "\"", -1 );

		closeIndex					= text_indexOff( include, "\"", openIndex + 1 );

	}

	char * fileName					= text_slice( include, openIndex + 1, closeIndex - 1 );

	return fileName;

}

char * resolve( char * path )
{

	struct array * pathParts	= text_split( path, "/" );

	int partsCount		= array_length( pathParts );

	array * validParts	= array_new();

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

		char * currentPart = array_get( pathParts, i );

		if( strcmp( currentPart, ".." ) == NULL ) {

			array_pop( validParts );

			continue;

		}

		if( strcmp( currentPart, "." ) == NULL ) {

			continue;

		}

		array_add( validParts, currentPart );

		//printf("currentPart:	%s\n", currentPart);

	}

	char * joinedText = text_join( validParts, "/" );

	int lastCharacterIndex	= strlen( path ) - 1;

	text * finalPath = text_new("");

	if( path[ 0 ] == 47 ) {

		text_append( finalPath, "/" );

	}

	text_append( finalPath, joinedText );

	if( path[ lastCharacterIndex ] == 47 ) {

		text_append( finalPath, "/" );

	}

	return finalPath->value;

}


void file_loadUnloadedFiles( struct array * unloadedFileNames, struct array * loadedFileNames, char * path ) {


	char * parentPath					= dirname( text_copy( path ) );


	struct file * fileInstance 			= malloc( sizeof( struct file ) );

	fileInstance->path 					= file_removeExtensionFromFileName( path );

	fileInstance->source				= file_getSource(fileInstance->path );

	printf(":: %s\n", fileInstance->path   );

	
	if( array_length( loadedFileNames ) == 0 ) {

		array_add( loadedFileNames, fileInstance->path );

	}

	file_extractMacros( fileInstance );



	int includeCount					= array_length( fileInstance->includes );


	//printf("include count:		%i\n", includeCount);
	
	for ( int k = 0; k < includeCount; ++k )
	{
		
		struct include * includeInstance	= array_get( fileInstance->includes, k );

		char * currentInclude		= includeInstance->path;

		char * includeFileName		= file_getFileNameFromIncludeFixed( currentInclude );

		char * includeFileBaseName	= file_removeExtensionFromFileName( includeFileName );



		if( file_isLibCFileName( includeFileBaseName ) ) {

			continue;

		}

	
		

		int charCount = strlen( includeFileBaseName );

		//printf("includeFileBaseName:	%s\n", includeFileBaseName);


		struct text * pathFromApplication 		= text_new( "" );

		text_append( pathFromApplication, parentPath );

		text_append( pathFromApplication, "/" );

		text_append( pathFromApplication, includeFileBaseName  );


		struct text * relativeFilePath 		= text_new( "../application/source/" );

		text_append( relativeFilePath, resolve( pathFromApplication->value )  );

		text_append( relativeFilePath, ".c" );

		char * absolutePath = realpath( relativeFilePath->value, NULL );

		//printf("relativeFromWorkingDirectory:	%s  %s\n", absolutePath, relativeFilePath->value);

		if( absolutePath == NULL ) {

			continue;

		}

		char * relativeFromWorkingDirectory = resolve(  pathFromApplication->value );




		if( file_hasLoadedFileName( relativeFromWorkingDirectory, loadedFileNames ) == 1 ) {

			continue;

		}

		if( fileSystem_exists( relativeFilePath->value ) ) {

			array_add( loadedFileNames, relativeFromWorkingDirectory );


			file_loadUnloadedFiles( unloadedFileNames, loadedFileNames, resolve( pathFromApplication->value ) );
			
			//printf("file exists\n\n");

		}

		/*

		struct text * testText 		= text_new( "../application/source/" );

		char * relativePath			= dirname( text_copy( includeFileBaseName ) );


		

		text_append( testText, ".c" );



		char * absolutePath	= realpath( "../application/source/", NULL );


		struct text * test2 		= text_new( "../application/source/" );

		text_append( test2, parentPath );

		text_append( test2, "/" );

		//text_append( test2, relativePath );



		char * realTest	= realpath( test2->value, NULL );


		printf("					--- '%s' '%s' \n", text_copy( includeFileBaseName ),realTest);
		

		if( fileSystem_exists( realTest ) ) {

			struct text * currentFullFileName =  text_new( realTest );

			text_append( currentFullFileName, "/" );

			text_append( currentFullFileName, includeFileBaseName );

			text_append( currentFullFileName, ".c" );

			char * goodAbsoluteFilePath = realpath( currentFullFileName->value, NULL );

			printf(" currentFullFileName:	%s \n", goodAbsoluteFilePath );

			file_loadUnloadedFiles( unloadedFileNames, loadedFileNames, goodAbsoluteFilePath );

		} else {

			printf("\nthis file does not exists %s\n\n", testText->value);

		}
		*/

	}

}