#include <string.h>
#include <stdio.h>

#include "parse.h"

#ifdef DEBUG

/* test¿ë ÇÔ¼ö */
extern void print_html_token( token_ptr tag ){

	token_ptr tmp = tag;
	param_ptr p;
	
	int i = 1;
	//int j;
	
	while( tmp != NULL ){
		
		printf( "%02d: %d, %s\n", i, tmp->type, tmp->str );
		tmp = tmp->next;
		
		//p = tmp->param_list;
		/*j = 1;
		while( p != NULL ){
			
			printf("-%02d: %s -> %s\n", j, p->param_name, p->param_value );
			j++;
			p = p->next;
			
		}*/
		
		i++;
		
	}
}

#endif

static void add_param_token( token_ptr tag, param_ptr par ){

	param_ptr tmp;
	
	if( tag->param_list == NULL )
		tag->param_list = par;
		
	else{
	
		tmp = tag->param_list;
		while( tmp->next != NULL )
			tmp = tmp->next;
		
		tmp->next = par;
		
	}
	
}

static void add_html_token( token_ptr* head, token_ptr tag ){

	token_ptr tmp;
	
	if( tag->str == NULL )
		free( tag );
		
	else{
		
		if( (*head) == NULL )
			(*head) = tag;
		
		else{
		
			tmp = *head;
			while( tmp->next != NULL )
				tmp = tmp->next;
			
			tmp->next = tag;
		
		}
		
	}
		
}

static token_ptr malloc_token( gint type ){

	token_ptr tag;
	
	tag = (token_ptr) g_malloc( sizeof(token) );
	
	tag->next = NULL;
	tag->param_list = NULL;
	tag->type = type;
	
	return tag;	
}

static char* my_strncpy( const char* pos, int len ){

	char* str;
	
	if( len < 1 )
		return NULL;
		
	else{
		
		str = (char*) malloc( sizeof(char) * (len+1) );
		if( len == 1 ){
			
			(*str) = *pos;
			(*(str+1)) = '\0';
			
		}
		else{
			
			memset( str, 0, sizeof(char) * (len+1) );
			strncpy( str, pos, len );
			
		}
		return str;
		
	}
	
}

/* ÀÏ¹Ý ÅØ½ºÆ® »óÅÂ */
static void get_html_token_case0( char** head, char* tail, token_ptr* token_head, void* next_function ){
	
	int token_len;
	token_ptr* tag_ptr;
	
	if( (*tail) == '<' ){					
		token_len = tail - head;
									
		tag_ptr = malloc_token( T_STR );
		tag_ptr->str = my_strncpy( head, token_len );
		add_html_token( &token_head, tag_ptr );
									
		head = tail + 1;
		stat = 1;	// Tag with Spaces
	}	
	
}

/* ¾ÕºÎºÐ¿¡ ½ºÆäÀÌ½º°¡ ÀÖÀ» ¼ö ÀÖ´Â tag »óÅÂ */
static void get_html_token_case1( char** head, char* tail, token_ptr* token_head, void* next_function ){
	
	if( (*tail) == '>' ){					
		head = tail + 1;
		stat = 0;					
	}
	else if( (*tail) == ' ' )
		head++;					
	else 
		stat = 2;	
}

/* ¾ÕºÎºÐ¿¡ ½ºÆäÀÌ½º°¡ ¾ø´Â tag »óÅÂ  */
static void get_html_token_case2( char** head, char* tail, token_ptr* token_head, void* next_function ){
	
	if( (*tail) == '>'  || (*tail) == ' ' ){					
		token_len = tail - head;
								
		tag_ptr = malloc_token( T_TAG );
		tag_ptr->str = my_strncpy( head, token_len );
		add_html_token( &token_head, tag_ptr );
						
		head = tail + 1;
		stat = ((*tail) == '>' )? 0 : 3;					
	}	
	
}

/* ¾Õ¿¡ ½ºÆäÀÌ½º°¡ ÀÖÀ» ¼ö ÀÖ´Â Param Name »óÅÂ.. */
static void get_html_token_case3( char** head, char* tail, token_ptr* token_head, void* next_function ){
	
	int token_len;
	token_ptr* tag_ptr;
	
	if( (*tail) == '>' ){
		head = tail + 1;
		stat = 0;	
	}
	else if( (*tail) == ' ' )
		head++;					
	else
		stat = 4;		
					
}

/* ¾Õ¿¡ ½ºÆäÀÌ½º°¡ ¾ø´Â  Param Name »óÅÂ */
static void get_html_token_case4( char** head, char* tail, token_ptr* token_head, void* next_function ){

	int token_len;
	param_ptr* par_ptr;
		
	if( (*tail) == '>' ){				
		head = tail + 1;
		stat = 0;						
	}
	else if( (*tail) == '='  || (*tail) == ' ' ){					
		token_len = tail - head;
										
		par_ptr = (param_ptr) g_malloc( sizeof(param_ptr) );					
					
		par_ptr->param_name = my_strncpy( head, token_len );
		par_ptr->next = NULL;				
										
		head = tail + 1;	 
		stat = ( (*tail) == '=' )? 6 : 5;					
	}	
	
}

/*  µÚ¿¡ ½ºÆäÀÌ½º°¡ ÀÖÀ» ¼ö ÀÖ´Â »óÅÂ·Î Param NameÀÌ ³¡³­ »óÅÂ */
static void get_html_token_case5( char** head, char* tail, token_ptr* token_head, void* next_function ){
	
	if( (*tail) == '>' ){
		free( par_ptr );
		par_ptr = NULL;
						
		head = tail + 1;
		stat = 0;
	}
	else if( (*tail) == ' ' )
		head++;
	else if( (*tail) == '=' ){
		head++;
		stat = 6;					
	}
	else{
		free( par_ptr );
		par_ptr = NULL; 	
		stat = 4;			
	}	
					
}

/* ¾Õ¿¡ ½ºÆäÀÌ½º°¡ ÀÖÀ» ¼ö ÀÖ´Â  Param value »óÅÂ */
static void get_html_token_case6( char** head, char* tail, token_ptr* token_head, void* next_function ){
	
	if( (*tail) == '>' ){
		g_free( par_ptr );
		par_ptr = NULL;
					
		head = tail + 1;
		stat = 0;
	}	
	else if( (*tail) == '"') {
		head++;
		stat = 8;
	}				
	else if( (*tail ) == ' ' )
		head++;
	else
		stat = 7;	
		
}

/* ¾Õ¿¡ ½ºÆäÀÌ½º°¡ ¾ø´Â  Param value »óÅÂ */
static void get_html_token_case7( char** head, char* tail, token_ptr* token_head, void* next_function ){
	
	int token_len;
	param_ptr* par_ptr;
		
	if( (*tail) == '>'  || (*tail) == ' ' ){					
		token_len = tail - head - 1;
										
		par_ptr = (param_ptr) g_malloc( sizeof(param_ptr) );					
					
		par_ptr->param_name = my_strncpy( head, token_len );
		par_ptr->next = NULL;				
					
		add_param_token( token_head, par_ptr );
		par_ptr = NULL;
					
		head = tail + 1;	 
		stat = ( (*tail) == '>' )? 0 : 5;					
	}	
	
}

/* "ÀÌ³ª ½ºÆäÀÌ½º¿Í »ó°ü¾ø´Â Param Value */
static void get_html_token_case8( char** head, char* tail, token_ptr* token_head, void* next_function ){
	
	if( (*tail) == '"' ){					
		token_len = tail - head;
										
		par_ptr = (param_ptr) g_malloc( sizeof(param_ptr) );					
					
		par_ptr->param_name = my_strncpy( head, token_len );
		par_ptr->next = NULL;				
					
		add_param_token( token_head, par_ptr );
		par_ptr = NULL;
					
		head = tail + 1;	 
		stat = 3;					
	}				
	
}

extern token_ptr get_html_token( const char *str ){

	void (*next_func) (char **head, char* tail, token_ptr* token_head, void* next_function );

	token_ptr token_head = NULL, tag_ptr; 	
	param_ptr par_ptr;
		
	char *head, *tail;
	int stat = 0, len, token_len, i;
	
	head = (char*)str;
	tail = head;
	len = strlen( str );
	
	for( i = 0 ; i < len ; i++ ){
		
		switch( stat ){
	
			case 0:	// ÀÏ¹Ý ÅØ½ºÆ®			
				if( (*tail) == '<' ){					
					token_len = tail - head;
									
					tag_ptr = malloc_token( T_STR );
					tag_ptr->str = my_strncpy( head, token_len );
					add_html_token( &token_head, tag_ptr );
										
					head = tail + 1;
					stat = 1;	// Tag with Spaces
				}
				break;
				
			case 1: // Tag with Space
			
				if( (*tail) == '>' ){					
					head = tail + 1;
					stat = 0;					
				}
				else if( (*tail) == ' ' )
					head++;					
				else 
					stat = 2;				
				break;
				
			case 2: // Tag with no space
				if( (*tail) == '>'  || (*tail) == ' ' ){					
					token_len = tail - head;
								
					tag_ptr = malloc_token( T_TAG );
					tag_ptr->str = my_strncpy( head, token_len );
					add_html_token( &token_head, tag_ptr );
						
					head = tail + 1;
					stat = ((*tail) == '>' )? 0 : 3;					
				}
				break;
				
			case 3: // Param Name with Space
				if( (*tail) == '>' ){
					head = tail + 1;
					stat = 0;	
				}
				else if( (*tail) == ' ' )
					head++;					
				else
					stat = 4;					
				break;
				
			case 4: // Param Name with no space
				if( (*tail) == '>' ){				
					head = tail + 1;
					stat = 0;						
				}
				else if( (*tail) == '='  || (*tail) == ' ' ){					
					token_len = tail - head;
										
					par_ptr = (param_ptr) g_malloc( sizeof(param_ptr) );					
					
					par_ptr->param_name = my_strncpy( head, token_len );
					par_ptr->next = NULL;				
										
					head = tail + 1;	 
					stat = ( (*tail) == '=' )? 6 : 5;					
				}
				break;
				
			case 5: // Param Name End with space
				if( (*tail) == '>' ){
					free( par_ptr );
					par_ptr = NULL;
									
					head = tail + 1;
					stat = 0;
				}
				else if( (*tail) == ' ' )
					head++;
				else if( (*tail) == '=' ){
					head++;
					stat = 6;					
				}
				else{
					free( par_ptr );
					par_ptr = NULL; 	
					stat = 4;			
				}		
				break;
				
			case 6: // Param value with space
				if( (*tail) == '>' ){
					g_free( par_ptr );
					par_ptr = NULL;
					
					head = tail + 1;
					stat = 0;
				}	
				else if( (*tail) == '"') {
					head++;
					stat = 8;
				}				
				else if( (*tail ) == ' ' )
					head++;
				else
					stat = 7;
				break;
				
			case 7: // Param value with no space
				if( (*tail) == '>'  || (*tail) == ' ' ){					
					token_len = tail - head - 1;
										
					par_ptr = (param_ptr) g_malloc( sizeof(param_ptr) );					
					
					par_ptr->param_name = my_strncpy( head, token_len );
					par_ptr->next = NULL;				
					
					add_param_token( token_head, par_ptr );
					par_ptr = NULL;
					
					head = tail + 1;	 
					stat = ( (*tail) == '>' )? 0 : 5;					
				}
				break;
				
			case 8: // Param Value with no space and "
				if( (*tail) == '"' ){					
					token_len = tail - head;
										
					par_ptr = (param_ptr) g_malloc( sizeof(param_ptr) );					
					
					par_ptr->param_name = my_strncpy( head, token_len );
					par_ptr->next = NULL;				
					
					add_param_token( token_head, par_ptr );
					par_ptr = NULL;
					
					head = tail + 1;	 
					stat = 3;					
				}			
				break;

		}
		tail++;
	
	}
	return token_head;
		
}

/* ÆÄ½ÌÇÏ¸é¼­ ¸¸µé¾î³½ html_token ¿¡ »ç¿ëµÈ ¸Þ¸ð¸®¸¦ ÀüºÎ ÇØÁ¦.. */
extern void free_all_html_token( token_ptr head ){

	token_ptr next, del;
	
	next = head;
	while( next != NULL ){
		
		del = next;
		next = del->next;
		
		free( del );
		
	}
		
}

extern char* str_replace( const char* str, const char* needle1, const char* needle2 ){

		char* var;
		char* tmp_pos;
		char* needle_pos;
		
		int count;
		int len;
		
		/* ¿øº» ¹®ÀÚ¿­º¸´Ù ¹Ù²Ù·Á´Â ¹®ÀÚ¿­ÀÌ ±ä °æ¿ì.. °¹¼ö¸¦ ¼¼¼­ ¸Þ¸ð¸® ÇÒ´ç-_- */
		if( strlen (needle1) < strlen (needle2) ){
		
			count = 0;
			tmp_pos = (char*)str;
			
			/* °³¼ö ¼¼±â.. */
			while( needle_pos = (char*) strcasestr( tmp_pos, needle1 ) ){
				
				tmp_pos = needle_pos + strlen (needle1);
				count++;
				
			}
			len = strlen(str) + (strlen(needle2) - strlen(needle1)) * count;
			var = (char*) g_malloc( sizeof(char) * (len + 1) );
			
		}	
		else {
			
			len = strlen(str);
			var = (char*) g_malloc( sizeof(char) * (len+1) );
			memset( var, 0, ( sizeof(char) * (len+1) ) );
			
		}
			
		/* Ä¡È¯ ½ÃÀÛ.. */
		tmp_pos = (char*) str;
		while( needle_pos = (char*)strcasestr( tmp_pos, needle1 ) ){
				
			len = needle_pos - tmp_pos;
				
			strncat( var, tmp_pos, len );
			strcat( var, needle2);
				
			tmp_pos = needle_pos + strlen (needle1);
					
		}
		strcat( var, tmp_pos );
		
		return var;

}

