
#include <math.h>

#include <index.h>

#include <text.h>

#include <stdlib.h>

#include <string.h>

#include <stdarg.h> // va_list

#include <ctype.h> // isspace

#include <array.h>

#include <ctype.h>

//#include <regex.h>



#define ARRAY_SIZE( arr ) ( sizeof( ( arr ) ) / sizeof( ( arr )[0] ) )

int text_findArgumentCloseIndex( char * body, int fromKey ) {

	int depth 		= 0;

	int hasStarted 	= -1;

	int count		= strlen( body );

	int active 					= 1;

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


		int character  = body[i];

		if( character == 34 || character == 39 ) {

			int previousCharacter  = body[i-1];

			if( previousCharacter != 92 ) {

				if( active == 1 ) {

					active = 0;

				} else {

					active = 1;

				}

			}

		}



		// '('
		if ( (int)body[i] == 40 ) {

			depth++;

			hasStarted = 1;
			
		}

		if( hasStarted == 1 && depth == 0 && active == 1 ) {

			return i;

		}

		// ')'
		if ( (int)body[i] == 41 ) {

			depth--;
			
		}


	}

	return -1;

}


void text_validateCurlyBrackets( char * source ) {

	int depth 		= 0;

	for (int j = 0; j < strlen( source ); ++j)
	{
		// '('
		if ( (int)source[j] == 123 ) {

			depth++;

		}

		// ')'
		if ( (int)source[j] == 125 ) {

			depth--;
			
		}

		if( depth < 0 ) {

			//int lineNumber = text_countLineBreaks( source, j );

			printf( ANSI_COLOR_RED "\n\n\n '}' is missing at line number. \n\n\n" ANSI_COLOR_RESET );

			exit( 0 );

			break;

		}

	}

	if( depth > 0 ) {

		printf( ANSI_COLOR_RED "\n\n\n\n\n\n '}' is missing. \n\n\n\n\n\n" ANSI_COLOR_RESET );

		exit( 0 );

	}

}


// opnieuw
int text_isValidNumber( char * a )
{

   for( int i = 0; i < strlen( a ); i++ )
   {
      //ASCII value of 0 = 48, 9 = 57. So if value is outside of numeric range then fail
      //Checking for negative sign "-" could be added: ASCII value 45.
      if (a[i] < 48 || a[i] > 57){

		return -1;

      }
   }
 
   return 1;
}

int text_findNumberOfLineBreaks( char * source ) {

	int numberOfLineBreaks = 0;

	for (int i = 0; i < strlen( source ); ++i)
	{
		if( (int)source[i] == 10 ) {

			numberOfLineBreaks++;

		}
	}

	return numberOfLineBreaks;

}


char * text_replaceChar( char * text, char needle, char replacement ) {

	char * copy		= text_copy( text );

	for (int i = 0; i < strlen( text ); ++i)
	{
		if( copy[i] == needle ) {

			copy[i] = replacement;

		}
	}

	return copy;

}

int text_findNextLineBreak( char * body, int currentKey ) {

	int count	= strlen( body );

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

		if( ( int ) body [ i ] == 10 ) {

			return i;

		}
	}

	return 0;

}


// opnieuw
char * text_removeAllWhiteSpaces( char * str ) {

	int i, j = 0;

	for (i = 0; str[i] != '\0'; i++) {

		if (str[i] != ' ') {

			str[j++] = str[i];

		}

	}

	str[j] = '\0';

	return str;
}

char * text_replace( char * haystack, char * needle, char * replaceWith )
{
	int count 				= 0;

	char *	tmp 			= haystack;

	int needleLength		= strlen( needle );

	struct array * keys		= array_new();

	while( tmp = strstr( tmp, needle ) ) {

		int key = (int)( tmp - haystack );
		
		array_add( keys, &key );

		tmp++;

		++count;
	}


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

		int currentKey	= *( int * ) array_get( keys, i );

		haystack = text_replaceAt( currentKey, currentKey + needleLength, haystack, replaceWith );

	}

	return haystack;

}

char * text_regexReplaceAll( char * haystack, char * needle, char * needleText, char * replacement ) {


//printf("\nreplace	%s  %s\n\n", needle, haystack);
	char * 			text 				= text_copy( haystack );

	int 			needleTextLength	= strlen( needleText );

	int length;

	int * fromKeys						= malloc( 1000 );

	int * toKeys  						= malloc( 1000 );

	int numberOfMatches 				= 0;

	char * output						= text;

	int skipToEnd						= 0;
/*

	

	char * 			expression 			= needle;//  "\\sclass\\s";

	regex_t     	regex;

	regmatch_t  	pmatch[1];

	int    			offset				= 0;

	int 			length;

	int 			needleTextLength	= strlen( needleText );

	char * output						= text;

	int * fromKeys						= malloc( 1000 );

	int * toKeys  						= malloc( 1000 );

	int numberOfMatches 				= 0;


	if ( regcomp( &regex, expression, REG_NEWLINE ) ) {

		return 0;

	}

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

		if ( regexec( &regex, text, ARRAY_SIZE( pmatch ), pmatch, 0 ) ){

			break;

		}

		offset 		+= ( int ) pmatch[0].rm_so;

		length 		= needleTextLength;

		int offsetFrom	= offset;

		offset		+= length;

		int offsetTo	= offset;

		fromKeys[numberOfMatches]		= offsetFrom;

		toKeys[numberOfMatches]		= offsetTo;

		offset++;

		numberOfMatches++;

		text 	+= ( int ) pmatch[0].rm_so + 1 + length;

	}
*/


	const char * error;
	unsigned char *name_table;
	unsigned int option_bits;
	int erroffset;
	int crlf_is_newline;
	int ovector[OVECCOUNT];
	int subject_length;
	int rc;
	int utf8;

	char * subject 			= ( haystack );

	subject_length 			= ( int ) strlen( subject );

	pcre * re 				= pcre_compile(	needle,              /* the needle */
											0,                    /* default options */
											&error,               /* for error message */
											&erroffset,           /* for error offset */
											NULL);                /* use default character tables */

	if ( re == NULL )
	{

		printf( "PCRE compilation failed at offset %d: %s\n", erroffset, error );

		return output;

	}

	rc = pcre_exec(	re,                   /* the compiled needle */
					NULL,                 /* no extra data - we didn't study the needle */
					subject,              /* the subject string */
					subject_length,       /* the length of the subject */
					0,                    /* start at offset 0 in the subject */
					0,                    /* default options */
					ovector,              /* output vector for substring information */
					OVECCOUNT );          /* number of elements in the output vector */


	if( rc < 0 ) {

		switch( rc )
		{
			case PCRE_ERROR_NOMATCH: 

				//printf("No match\n"); 

			break;

			default: 

				printf("Matching error %d\n", rc); 

			break;

		}

		pcre_free( re );     /* Release memory used for the compiled needle */

		return output;

	} 
//	printf("\nMatch succeeded at offset %d\n", ovector[0]);

	//lexer_add( currentLexer, ovector[0], token );

	if( skipToEnd == 0 ) {

		int offset 	= ovector[0];

		length 		= needleTextLength;

		int offsetFrom	= offset;

		offset		+= length;

		int offsetTo	= offset;

		fromKeys[numberOfMatches]		= offsetFrom;

		toKeys[numberOfMatches]			= offsetTo;

		offset++;

		numberOfMatches++;


	/* See if CRLF is a valid newline sequence. */

	crlf_is_newline =	option_bits == PCRE_NEWLINE_ANY ||
						option_bits == PCRE_NEWLINE_CRLF ||
						option_bits == PCRE_NEWLINE_ANYCRLF;

	/* Loop for second and subsequent matches */

	for (;;)
		{
		int options = 0;                 /* Normally no options */
		int start_offset = ovector[1];   /* Start at end of previous match */

		/* If the previous match was for an empty string, we are finished if we are
		at the end of the subject. Otherwise, arrange to run another match at the
		same point to see if a non-empty match can be found. */

		if (ovector[0] == ovector[1])
		{
		if (ovector[0] == subject_length) break;
		options = PCRE_NOTEMPTY_ATSTART | PCRE_ANCHORED;
		}

		/* Run the next matching operation */

		rc = pcre_exec(
		re,                   /* the compiled needle */
		NULL,                 /* no extra data - we didn't study the needle */
		subject,              /* the subject string */
		subject_length,       /* the length of the subject */
		start_offset,         /* starting offset in the subject */
		options,              /* options */
		ovector,              /* output vector for substring information */
		OVECCOUNT);           /* number of elements in the output vector */


		if (rc == PCRE_ERROR_NOMATCH)
		{
			if (options == 0) 
				break;                    				/* All matches found */

			ovector[1] = start_offset + 1;              /* Advance one byte */

			if (	crlf_is_newline &&                      /* If CRLF is newline & */
					start_offset < subject_length - 1 &&    /* we are at CRLF, */
					subject[start_offset] == '\r' &&
					subject[start_offset + 1] == '\n') {

				ovector[1] += 1;                          /* Advance by one more. */

			} else if ( utf8 ) {                     /* Otherwise, ensure we */
			                                      /* advance a whole UTF-8 */
				while (ovector[1] < subject_length)       /* character. */
				{
					if ((subject[ovector[1]] & 0xc0) != 0x80) 
						break;
					ovector[1] += 1;
				}

			}

			continue;    /* Go round the loop again */
		}

		/* Other matching errors are not recoverable. */

		if (rc < 0)
		{
			printf("Matching error %d\n", rc);

			pcre_free(re);    /* Release memory used for the compiled needle */

			return output;
		}

		/* Match succeeded */

		//printf("\nMatch succeeded again at offset %d\n", ovector[0]);

		offset 		= ovector[0];

		length 		= needleTextLength;

		offsetFrom	= offset;

		offset		+= length;

		offsetTo	= offset;

		fromKeys[numberOfMatches]		= offsetFrom;

		toKeys[numberOfMatches]			= offsetTo;

		offset++;

		numberOfMatches++;



		/* The match succeeded, but the output vector wasn't big enough. */
	}

	printf( "\n" );

	pcre_free( re );       /* Release memory used for the compiled needle */

	}

	//for (int i = 0; i < numberOfMatches; ++i)
	//{

	for (int i = numberOfMatches-1; i >= 0; i--)
	{
		int fromKey	= fromKeys[i];

		int toKey	= toKeys[i];

		printf("\n1111		%i  %i\n\n", fromKey, toKey);

		output = text_replaceAt( fromKey, toKey, output, replacement );

	}

	return output;

}

char * text_replaceAll( char * target, const char * needle, const char * replacement )
{
    char buffer[1024] = { 0 };
    char *insert_point = &buffer[0];
    const char *tmp = target;
    size_t needle_len = strlen(needle);
    size_t repl_len = strlen(replacement);

    while (1) {
        const char *p = strstr(tmp, needle);

        // walked past last occurrence of needle; copy remaining part
        if (p == NULL) {
            strcpy(insert_point, tmp);
            break;
        }

        // copy part before needle
        memcpy(insert_point, tmp, p - tmp);
        insert_point += p - tmp;

        // copy replacement string
        memcpy(insert_point, replacement, repl_len);
        insert_point += repl_len;

        // adjust pointers, move on
        tmp = p + needle_len;
    }

    // write altered string back to target
    strcpy(target, buffer);

    return target;
}

/*
char * text_regexReplaceAll2( char * haystack, char * needle, char * needleText, char * replacement ) {

	printf("\nreplace	%s  %s\n\n", needle, haystack);

	//text_regexReplaceAll2( haystack,  needle, needleText, replacement );

	char * 			expression 			= needle;//  "\\sclass\\s";

	regex_t     	regex;

	regmatch_t  	pmatch[1];

	int    			offset				= 0;

	int 			length;

	int 			needleTextLength	= strlen( needleText );

	char * text							= haystack;

	char * output						= haystack;

	int * fromKeys						= malloc( 1000 );

	int * toKeys  						= malloc( 1000 );

	int numberOfMatches 				= 0;


	if ( regcomp( &regex, expression, REG_NEWLINE ) ) {

		return 0;

	}

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

		if ( regexec( &regex, text, ARRAY_SIZE( pmatch ), pmatch, 0 ) ){

			break;

		}

		offset 		+= ( int ) pmatch[0].rm_so;

		length 		= needleTextLength;

		int offsetFrom	= offset;

		offset		+= length;

		int offsetTo	= offset;

		fromKeys[numberOfMatches]		= offsetFrom;

		toKeys[numberOfMatches]		= offsetTo;

		offset++;

		numberOfMatches++;

		text 	+= ( int ) pmatch[0].rm_so + 1 + length;

	}

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

	//for (int i = numberOfMatches-1; i >= 0; i--)
	//{
		int fromKey	= fromKeys[i];

		int toKey	= toKeys[i];

		printf("2222		%i  %i\n\n", fromKey, toKey);

		output = text_replaceAt( fromKey, toKey, output, replacement );

	}

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

	return output;

}
*/
char * text_replaceAt( int fromKey, int toKey, char * target, char * source ) {

	//char * newText	 	= malloc( sizeof( char * ) * 10000 );

	struct text * newText 		= text_new("");

	int length					= strlen( target );

	char * beginText 			= text_slice( target, 0, fromKey - 1 );

	char * endText 				= text_slice( target, toKey, length );

	text_append( newText, beginText );

	text_append( newText, source );

	text_append( newText, endText );

	return newText->value;

}

struct text * text_new( char * value ) {

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

	pointer->length 		= strlen( value );

	pointer->capacity  		= 256;

	text_constructor( pointer , value );

	return pointer;

}

void text_constructor( struct text * this, char * value ) {

	if( this->length > this->capacity ) {

		this->capacity = pow( 2, ceil( log( this->length ) / log( 2 ) ) ) * 2;

	}

	this->value			= malloc( sizeof( char ) * this->capacity );

	memcpy( this->value, value, this->length );

	this->value[ this->length ] = 0;

}

void text_resize( struct text * this, int size ) {

	//printf("      -----------               realocate: %i \n", size);

	char * value		= realloc( this->value, sizeof( char ) * size );


	this->value			= value;

	this->capacity		= size;

}


struct text * text_append( struct text * this, const char * value ) {

	int originalLength 	= this->length;

	int sourceLength	= strlen( value );

	this->length		+= sourceLength;

	if( this->length + 1  >= this->capacity ) {

		if( this->length + 1 > this->capacity * 2 ) {

			this->capacity 	= pow( 2, ceil( log( this->length ) / log( 2 ) ) );

			text_resize( this,  this->capacity * 2 );

		} else {

			text_resize( this,  this->capacity * 2 );

		}

		//printf("buffer has been resized:		capacity %i 		 length %i \n", this->capacity, this->length);

	}


	memcpy( this->value + originalLength, value, sourceLength );

	this->value[this->length] = 0;

	return this;

}


void text_free( struct text * this ) {

	free( this->value );

}

char * text_removeSlashFromStart( char * filePath ) {

	if( filePath[0] == 47 ) {

		memmove( filePath, filePath + 1, strlen( filePath ) );

	}

	return filePath;

	//filePath[strlen( filePath )] = 0;

}

struct text * text_appendDebug( struct text * this, const char * value ) {

	int originalLength 	= this->length;

	int newValueLength	= strlen( value );

	this->length		+= newValueLength;


	if( this->length > this->capacity ) {

		if( this->length > this->capacity * 2 ) {

			this->capacity 	= pow( 2, ceil( log( newValueLength ) / log( 2 ) ) );

			text_resize( this,  this->capacity * 2 );

		} else {

			text_resize( this,  this->capacity * 2 );

		}

	}

	printf("debug append: 	this->value	'%s'  originalLength: '%i' 	target: '%s'   newValueLength: '%i'   \n\n\n\n\n", this->value, originalLength, value, newValueLength );

	memmove( this->value + originalLength, value, newValueLength );

	//this->value[this->length] = 0;

	return this;

}

int text_exists( char * phrase, char * word ) {

	if ( strstr( phrase, word ) != NULL ) {

		return 1;

	}

	return -1;

}


char * text_fromNumber( int number ) {

	char * textNumber = malloc(sizeof(char)*20);

	sprintf(textNumber, "%d", number);

	return textNumber;

}

int text_findPreviousLineBreak( char * body, int currentKey ){

	for (int i = currentKey; i >= 0; --i)
	{
		if( ( int ) body [ i ] == 10 ) {

			return i;

		}
	}

	return 0;

}



char * text_concatenate( char * a, char * b ) {

	int lengthA 			= strlen( a );

	int lengthB 			= strlen( b );

	char * pointer 		= a;

	char * copy				= ( char * ) malloc( ( lengthA + lengthB + 1 ) * sizeof( char ) );

	int idx = 0;

	while ( * pointer != '\0' ){

		copy[idx++] = *pointer++;

	}

	pointer = &b[0];

	while (*pointer != '\0'){

		copy[idx++] = *pointer++;

	}

	copy[idx++] = '\0';

	return &copy[0];

}


int text_findQuoteCloseIndex( char * body, int fromKey ) {

	int hasStarted 	= -1;

	int count			= strlen( body );

	int active 				= 1;

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


		int character  = body[i];

		if( character == 34 || character == 39 ) {

			hasStarted = 1;

			int previousCharacter  = body[i-1];

			if( previousCharacter != 92 ) {

				if( active == 1 ) {

					active = 0;

				} else {

					active = 1;

				}

			}

		}

		if( hasStarted == 1 && active == 1 ) {

			return i;

		}


	}

	return -1;

}


int text_seekParenthesesLeftToRight( char * body, int currentKey ) {

	int count	= strlen( body );

	for (int i = currentKey; i < count; ++i)
	{
		
		if( body[ i ] > 65 || body[ i ] == 34 ) {

			return i;

		}


	}

	return -1;
	
}


int text_findFirstNextCharacterNotWhiteSpace( char * body, int fromKey ) {



	int depth = 0;

	int count = strlen( body );

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

		if( !isspace( body[i] ) ) {

			return i;

		}

	}

	return -1;
	

}

int text_findFirstNextCharacterNotWhiteSpaceNotParenthesis( char * body, int fromKey ) {

	int depth = 0;

	int count = strlen( body );

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

		int character = body[i];

		if( !isspace( character ) && character != 40 ) {

			return i;

		}

	}

	return -1;
	

}

int text_text_findFirstCharacterIndexbackwards( char * body, int fromKey ) { 

	for (int i = fromKey; i >= 0; --i)
	{

		if( !isspace( body[i] ) ) {

			return i;

		}

	}

	return -1;

}


int text_findFirstCharacterReverse( char * body, int fromKey ) {

	int depth = 0;

	int hasStarted = -1;

	for (int i = fromKey; i >= 0; --i)
	{
		// ')'
		if( !isspace( body[i] ) ) {

			return body[i];

		}

	}

	return -1;

}




char * text_reverse( char * str ) {
    char tmp, *src, *dst;
    int len;
    if (str != NULL)
    {
        len = strlen (str);
        if (len > 1) {
            src = str;
            dst = src + len - 1;
            while (src < dst) {
                tmp = *src;
                *src++ = *dst;
                *dst-- = tmp;
            }
        }
    }
    return str;
}

char * text_copy( char * a ) {

	char * newCopy = malloc( sizeof( char ) * strlen( a ) + 1 );

	strcpy( newCopy, a );

	return newCopy;
	
}

char * text_formatLength( char * a, int newLength ) {

	char copyOfText[newLength];// 	= text_copy( a );

	int length 			= strlen( a );

	for (int i = 0; i < length; ++i)
	{
		copyOfText[i] = a[i];
	}

	for (int i = length; i < newLength; ++i)
	{
		copyOfText[i] = ( char ) 46;//32
	}

	//copyOfText[newLength] = ( char ) 0;

	return copyOfText;

}

int text_text_findFirstCharacterIndexFromIndex( char * text, char * character, int fromIndex ) {

	int firstKeyIsHit	= -1;

	int characterInteger = (int)character[0];

	for (int i = fromIndex; i < strlen(text); ++i)
	{

		int charNumber = ( int ) text[i];

		if( firstKeyIsHit == 1 ) {

			if( (int)text[i] == characterInteger ) {

				return i;

			}

		}
		

		if( charNumber > 47 ) {

			firstKeyIsHit = 1;

		}
		
	}

	return -1;

}

int text_getIndexBeforeWord( char * body, int currentKey ) {

	int firstKeyIsHit	= -1;
	
	int notWithinQuotes	= 1;

	for (int i = 1; i < 30; ++i)
	{
		int charNumber = (int)body[currentKey-i];

		if( charNumber == 34 || charNumber == 39 ) {

			int previousCharacter  = body[i-1];

			if( previousCharacter != 92 ) {

				if( notWithinQuotes == 1 ) {

					notWithinQuotes = 0;

				} else {

					notWithinQuotes = 1;

				}

			}

		}


		if( firstKeyIsHit == 1 ) {

			if( charNumber < 48 && charNumber != 60 && charNumber != 62 && notWithinQuotes ) {

				return currentKey - i + 1;

			}

		}
		

		if( charNumber > 48 && charNumber != 60 && charNumber != 62  ) {

			firstKeyIsHit = 1;

		}
		
	}

	return -1;
}


int text_indexOff( char * source, char * token, int fromIndex ) {

	char * found;//= strstr( source, token ); 

	if( fromIndex < 1) {

		found = strstr( source, token ); 

	} else {

		found = strstr( source + fromIndex, token ); 

	}
	

	if (found != NULL)                    
	{

	  return found - source;         

	} else {

		return -1;

	}

}

int text_findFirstCharacterIndex( char * text, char * character ) {

	//char * e = strchr( text, character );

	//int index = (int)(e - text);

	return strcspn( text, character );

}

char * text_join( struct array * arrayInstance, char * separator ) {

	int argumentCount 	= array_length( arrayInstance );

	int totalCount = 0;

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

		if( j != 0 ) {

			totalCount++;

		}

		int currentCount = strlen( argumentText );

		totalCount 		+= currentCount;

		//printf("totalCount:	%i\n", totalCount);

	}

	char * output		= ( char * ) malloc( totalCount );

	totalCount = 0;

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

		if( j != 0 ) {

			//strcat( output, separator );

			memcpy( output + totalCount, separator, 1 );

			totalCount++;

		}

		//printf("??	%s\n", argumentText);

		//strcat( output, text_copy( argumentText ) );

		char * copy = text_copy(argumentText);

		int currentCount = strlen( copy );

		

		//printf("memcpy, %i, %s, %i", totalCount, copy, currentCount);

		memcpy( output + totalCount, copy, currentCount );

		totalCount 		+= currentCount;


	}

	output[totalCount] 	= '\0';

	//printf("concat	%s\n", output);

	return output;

}

int text_countLineBreaks( char * text, int toIndex ) {

	int lineBreakCount = 0;

	if( toIndex == -1 ) {

		toIndex = strlen( text );

	}

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

		char currentCharacter = text[j];

		if( ( int ) currentCharacter == 10 ) {

			lineBreakCount++;

		}
	
	}

	return lineBreakCount;

}


struct array * text_splitArguments( char * argumentsText ) {

	int count 					= strlen( argumentsText );

	int active 					= 1;

	int previousCharacterIndex	= 0;

	struct array * keys 		= array_new();


	for (int i = 0; i < count; ++i)
	{
		int character  = argumentsText[i];

		if( character == 34 || character == 39 ) {

			int previousCharacter  = argumentsText[i-1];

			if( previousCharacter != 92 ) {

				if( active == 1 ) {

					active = 0;

				} else {

					active = 1;

				}

			}

		}

		if( active == 1 ) {

			if( character == 44 ) {

				//printf("%i\n", i);

				//indices[index++] = i;

				int wordLength	= i - previousCharacterIndex;

				char * word		= malloc( wordLength + 1 );

				memcpy( word, argumentsText + previousCharacterIndex, wordLength );

				//printf("	%i	%s\n", i, word);

				array_add( keys, word );

				previousCharacterIndex = i + 1;

			}

		}
		
	}

	if( previousCharacterIndex != 0 ) {

		int wordLength	= count - previousCharacterIndex;

		char * word		= malloc( wordLength + 1 );

		memcpy( word, argumentsText + previousCharacterIndex, wordLength );

		array_add( keys, word );

	} else {

		int hasOneArgument = -1;

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

			char character  = argumentsText[i];

			if( !isspace( character ) ) {

				hasOneArgument = 1;

			}

		}

		if( hasOneArgument == 1 ) {

			array_add( keys, argumentsText );
			
		} 

	}

	return keys;

}
/*
struct array * text_split( char * text, char * separator ) {

	char * token;

	token = strtok( text, separator );

	struct array * parts = array_new();


	while( token != NULL ) {

		if( token ) {

			array_add( parts, token );

		} 

		token = strtok( NULL, separator );

	}

	return parts;

}
*/
struct array * text_split( char * haystack, char * needle )
{
	struct array * keys 	= array_new();

	char * haystackCopy 	= text_copy( haystack );

    char * token 			= strtok( haystackCopy, needle);
  
    int i 				= 0;

    while( token ) {

       	array_add( keys, token );

        token = ( char * ) strtok( NULL, needle );

    }

	return keys;

}

char * text_extractWordBeforeKey( char * body, int currentKey ) {

	char * invertedName = malloc( sizeof( char * ) * 30 );

	int firstKeyIsHit	= -1;

	for (int i = 1; i < 30; ++i)
	{
		int charNumber = (int)body[currentKey-i];

		if( firstKeyIsHit == 1 ) {

			if( charNumber < 47 ) {

				invertedName[i-1] = '\0';


				i = 100;

			}

		}
		

		if( charNumber > 47 ) {

			firstKeyIsHit = 1;

			invertedName[i-1] = (char)body[currentKey-i];

		}
		
	}

	return  text_reverse( text_removeWhiteSpaces( invertedName ) );

}

char * text_removeSpaces( char * s ) {

    char* d = s;

    do {

        while (*d == ' ') {

            ++d;
            
        }

    } while (*s++ = *d++);

 	return s;
 	
}

int text_extractIndexAtWhiteSpace( char * body, int currentKey ) {

	int firstKeyIsHit	= -1;

	for (int i = 1; i < 60; ++i)
	{
		int charNumber = ( int ) body[currentKey+i];

		if( firstKeyIsHit == 1 ) {

			if( charNumber < 47 || charNumber == 59 ) {

				return i + currentKey;

			}

		}
		

		if( body[currentKey+i] > 47 ) {

			firstKeyIsHit = 1;

		}
		
	}

	return -1;

}

int text_extractIndexAfterWord( char * body, int currentKey ) {

	int firstKeyIsHit	= -1;

	for (int i = 1; i < 60; ++i)
	{
		int charNumber = ( int ) body[currentKey+i];

		if( firstKeyIsHit == 1 ) {

			if( charNumber < 47 ) {

				return i + currentKey;

			}

		}
		

		if( charNumber > 47 ) {

			firstKeyIsHit = 1;

		}
		
	}

	return -1;

}


char * text_extractWordAfterKey( char * body, int currentKey ) {

	return "";
/*
	char * invertedName = malloc( sizeof( char * ) * 30 );

	int firstKeyIsHit	= -1;

	for (int i = 1; i < 30; ++i)
	{
		int charNumber = (int)body[currentKey-i];

		if( firstKeyIsHit == 1 ) {

			if( charNumber < 47 ) {

				invertedName[i-1] = '\0';


				i = 100;

			}

		}
		

		if( charNumber > 47 ) {

			firstKeyIsHit = 1;

			invertedName[i-1] = (char)body[currentKey-i];

		}
		
	}

	return  text_reverse(text_removeWhiteSpaces( invertedName ) );;
*/
}

char * text_concatenateMultiple(int count, ...)
{
	va_list ap;
	int i;

	// Find required length to store merged string
	int len = 1; // room for NULL
	va_start(ap, count);
	for(i=0 ; i<count ; i++)
	    len += strlen(va_arg(ap, char*));
	va_end(ap);

	// Allocate memory to concat strings
	char *merged = calloc(sizeof(char),len);
	int null_pos = 0;

	// Actually concatenate strings
	va_start(ap, count);
	for(i=0 ; i<count ; i++)
	{
	    char *s = va_arg(ap, char*);
	    strcpy(merged+null_pos, s);
	    null_pos += strlen(s);
	}
	va_end(ap);

	return merged;
}

char * text_slice( char * str, int start, int end )
{

	const int len = strlen(str);

	char * buffer = malloc(sizeof( char ) * len);

	int j = 0;

	for ( int i = start; i <= end; ++i ) {

		buffer[j++] = str[i];

	}

	buffer[j] = 0;

	return buffer;
}


char * text_removeWhiteSpacesLeft(char *s)
{

    while(isspace(*s)) s++;

    return s;

}

bool text_contains( char * s, char * needle ) {

	if (strstr( s, needle ) != NULL ) {
	
		return true;

	}

	return false;

}

char * text_removeWhiteSpacesRight( char * s )
{
    //char* back = s + strlen(s);
	int length = strlen( s );

	int sliceChars  = 0;

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

		char currentChar = s[length - 1 - i];

		sliceChars++;


		if( !isspace( currentChar ) ) {

			s[length  - sliceChars + 1] = '\0';

			break;

		}

	}

	

	return s;
}

char * text_removeWhiteSpaces( char * s )
{

    return text_removeWhiteSpacesRight( text_removeWhiteSpacesLeft( s ) ); 

}