#include  "JSON.h"

int make_json_data(JSON_ELEMENT *json, char *json_data){
	int len=0;
	if (json->name){
		if (json_data){
			sprintf( json_data+len, "\"%s\":", json->name);
		}
		len += 2 + 1 + strlen(json->name); //  "xxxxxx":
	}
	
	if (	json->child_type == JSON_OBJ ||
		json->child_type == JSON_ARRAY ){
		if (json_data){
			json_data[len]=json->child_type == JSON_OBJ?'{':'[';
			len++;
			len+=make_json_data( (JSON_ELEMENT *) json->child, json_data+len);
			json_data[len]=json->child_type == JSON_OBJ?'}':']';
			len++;
		}else{
			len += 2 ; 
			len += make_json_data( (JSON_ELEMENT *) json->child, NULL);
		}
	}
	else if (	json->child_type == JSON_STR ){
		if (json->child) {
			if (json_data){
				sprintf( json_data+len, "\"%s\"", (char *)json->child);
			}
			len += strlen((char *)json->child); //  "xxxxxx"
		}else{
			if (json_data){
				strcpy( json_data+len, "\"\"");
			}
		}
		len += 2;
	}
	else if (	json->child_type == JSON_OTHER ){
		if (json->child) {
			if (json_data){
				sprintf( json_data+len, "%s", (char *)json->child);
			}
			len += strlen((char *)json->child); //  "xxxxxx"
		}
	}

	if (json->next){
		if (json_data){
			json_data[len]=',';
			len++;
			len+=make_json_data( (JSON_ELEMENT *) json->next, json_data+len);
		}else{
			len++;
			len+=make_json_data( (JSON_ELEMENT *) json->next, NULL );
		}
	}
	return len;
}

char * create_json(JSON_ELEMENT *json){
	int len=0;
	char * json_data=NULL;
	len = make_json_data(json, NULL)+1;
	json_data = calloc(len,1);
	make_json_data(json, json_data);
	json_data[len-1]='\0';
	return json_data;
}

JSON_ELEMENT * parse_json(char **data, JSON_TYPE type){
	char  *ps,*pe;
	JSON_ELEMENT  * pcrrent,*pentery;
	char  *src=*data;
	int	flg=0;
	JSON_TYPE  status=JSON_NULL;
	JSON_TYPE cmp_type=JSON_NULL;
	ps=NULL;
	pe=NULL;
	
	pentery=NULL;
	pcrrent=pentery;
	pcrrent= calloc(1, sizeof(JSON_ELEMENT));

	while(*src){
		char ch=*src++;
		switch(ch) {
			case '{':
			case '[':
				status=(ch=='{')?JSON_OBJ:JSON_ARRAY;
				if (!pcrrent){
					pcrrent= calloc(1, sizeof(JSON_ELEMENT));
				}
				pcrrent->child_type=status;
				pcrrent->child=(void *) parse_json( &src, status );
			    break;
			case '}':
			case ']':
				cmp_type=(ch=='}')?JSON_OBJ:JSON_ARRAY;
				if ( type==cmp_type && status == JSON_NULL ){
					if ( ps ){
						if ( pe ){
							pcrrent->child_type=JSON_STR;
						}else{
							pe=src-1;
							pcrrent->child_type=JSON_OTHER;
						}
						pcrrent->child = calloc(1, pe - ps + 1);
						strncpy(pcrrent->child, ps, pe - ps);
						ps=NULL;
						pe=NULL;
					}
					pcrrent->next=NULL;
					flg=1;
				}
			    break;
			case ',':
				if ( status==JSON_NULL ){
					if ( ps ){
						if ( pe ){
							pcrrent->child_type=JSON_STR;
						}else{
							pe=src-1;
							pcrrent->child_type=JSON_OTHER;
						}
						pcrrent->child = calloc(1, pe - ps + 1);
						strncpy(pcrrent->child, ps, pe - ps);
						ps=NULL;
						pe=NULL;
					}
					
					if (pcrrent){
						pcrrent->next = calloc(1, sizeof(JSON_ELEMENT));
						pcrrent=pcrrent->next;
					}else{
						printf("err----,----------\n");
						// pcrrent= calloc(1, sizeof(JSON_ELEMENT));
					}


				}
			    break;
			case '"':
				if ( status==JSON_STR ){
					status=JSON_NULL;
					if (ps){
						pe=src-1;
					}else{
						printf("err----\"-end----------\n");
					}
				}else{
					status=JSON_STR;
					if (!ps){
						ps=src;
					}else{
						printf("err----\"-start----------\n");
					}
				}
			    break;
			case ':':
				if ( status==JSON_NULL ){
					if ( ps ){
						if ( !pe ){
							pe=src-1;
							pentery->child_type=JSON_OTHER;
						}
						pcrrent->name = calloc(1, pe - ps + 1);
						strncpy(pcrrent->name, ps, pe - ps);
						ps=NULL;
						pe=NULL;
					}else{
						printf("err-----:----------\n");
					}
				}
			    break;
			default:
				if (isspace(ch)){
					if ( status==JSON_NULL ){
						if (ps){
							if ( !pe ){
								pe=src-1;
							}
						}
					}
				}else{
					if ( status==JSON_NULL ){
						if (!ps){
							ps=src-1;
						}
					}
				}
		}
		if (!pentery){
			pentery=pcrrent;
		}
		if (flg)
			break;
	}
	*data=src;
	return pentery;
}

JSON_ELEMENT * get_json(char *data){
	JSON_ELEMENT  *pentery;
	char *src=data;
	
	pentery=parse_json( &src, JSON_NULL);
	
	return pentery;
}

void  free_json(JSON_ELEMENT *json){
	
	if (json->name){
		printf("json->name[%s]\n",json->name);
		free(json->name);
	}
	if ( 	json->child_type==JSON_STR||
		json->child_type==JSON_OTHER	){
		printf("json->child_type[%d]\n",json->child_type);
		printf("json->child[%s]\n",(char*)json->child);
		free(json->child);
	}else if ( 	json->child_type==JSON_OBJ ||
			json->child_type==JSON_ARRAY){
				printf("json->child_type[%d]\n",json->child_type);
				printf("json->child{\n");
				free_json((JSON_ELEMENT *)json->child);
				printf("json->child}\n");
	}
	if (json->next){
		printf("json->next{\n");
		free_json(json->next);
		printf("json->next}\n");
	}
	
}
