/*
 *  Gaycko        Text mode web browser
 *  Copyright (c) 2011 Jean-Yves Lamoureux <jylam@lnxscene.org>
 *                All Rights Reserved
 *
 *  This library is free software. It comes without any warranty, to
 *  the extent permitted by applicable law. You can redistribute it
 *  and/or modify it under the terms of the Do What The Fuck You Want
 *  To Public License, Version 2, as published by Sam Hocevar. See
 *  http://sam.zoy.org/wtfpl/COPYING for more details.
 */
#include <config.h>
#include <stdio.h>
#include <string.h>
#include "dom.h"
#include "helpers/str.h"

gDOM *gaycko_convert_dom(htmlDocPtr doc) {

	gDOM *dom = malloc(sizeof(gDOM));
	dom->root = NULL;  
	htmlNodePtr root = xmlDocGetRootElement(doc);
	gNode **r = NULL;
	gNode *ret = NULL;

	if(root != NULL)
	{
		ret = explore(r, root, 0, NULL);
	}

	dom->root = ret;

	return dom;
}


gNode *add_node(htmlNodePtr node) {

	gNode *e;
	e = malloc(sizeof(gNode));
	e->children_count  = 0;
	e->children        = NULL;
	e->attribute_count = 0;
	e->attributes      = NULL;
	e->text            = NULL;

	e->properties = malloc(sizeof(gProperty));
    e->properties->x = 0;
    e->properties->y = 0;
    e->properties->width = 0;
    e->properties->height = 0;
    
	if(!node->name) {
		e->name = strdup("UNKNOW");
		e->type = ELEM_UNKNOW;
		return e;	
	}
	
	e->name = (char*)strdup((const char*)node->name);
	if(!strncmp(e->name, "html", 4)) {
		e->type = ELEM_HTML;
	}else if(!strncmp(e->name, "head", 4)) {
		e->type = ELEM_HEAD;
	}else if(!strncmp(e->name, "title", 5)) {
		e->type = ELEM_TITLE;
	}else if(!strncmp(e->name, "meta", 4)) {
		e->type = ELEM_META;
	}else if(!strncmp(e->name, "body", 4)) {
		e->type = ELEM_BODY;
	}else if(!strncmp(e->name, "h1", 2)) {
		e->type = ELEM_H1;
	}else if(!strncmp(e->name, "br", 2) || !strncmp(e->name, "br ", 3)) {
		e->type = ELEM_BR;
	}else if(!strncmp(e->name, "p", 1)) {
		e->type = ELEM_P;
	}else if(!strncmp(e->name, "img", 3)) {
		e->type = ELEM_IMG;
	}else if(!strncmp(e->name, "table", 3)) {
		e->type = ELEM_TABLE;
	}else if(!strncmp(e->name, "tr", 3)) {
		e->type = ELEM_TR;
	}else if(!strncmp(e->name, "td", 3)) {
		e->type = ELEM_TD;
	}else if(!strncmp(e->name, "text", 4)) {
		e->type = ELEM_TEXT;
		e->text = (char*)strdup((const char*)xmlNodeGetContent(node));
		strip_eol(e->text);
		strip_spaces(&e->text);
	}else {
		e->type = ELEM_UNKNOW;
		printf("Unknow tag '%s'\n", e->name);   
	}

	if(node->properties) {
		for(xmlAttrPtr attr = node->properties; attr != NULL; attr = attr->next) {
			e->attributes = realloc(e->attributes, sizeof(gAttribute)*(e->attribute_count+1));
			e->attributes[e->attribute_count].name = strdup((const char*)attr->name);
			e->attributes[e->attribute_count].value = strdup((char*)attr->children->content);
            		e->attribute_count++;
		}
	}

	return e;
}


gNode* explore(gNode **elem, htmlNodePtr hnode, unsigned int level, gNode *parent)
{
	unsigned int c = 0;
	for(htmlNodePtr node = hnode; node != NULL; node = node->next)
	{
		gNode *child = add_node(node);
		child->level = level;

		if(elem) elem  = realloc(elem, sizeof(gNode*)*(c+1));
		else elem = malloc(sizeof(gNode*));


		elem[c] = child;

		c++;

		if(node->type == XML_ELEMENT_NODE)
		{
			if(node->children != NULL) {
				explore(child->children,
						node->children,
						level+1,
						child);
			} else {
				free(child->children);
				child->children = NULL;
			}
		}         
		if(parent) {
			parent->children = realloc(parent->children, sizeof(gNode*)*(parent->children_count+1));
			parent->children[parent->children_count] = child;
			parent->children_count++;
		}
	}
	return *elem;
}


void destroy_node(gNode *elem) {
	if(!elem) return;

	unsigned int a;
	for(a = 0; a < elem->attribute_count; a++) {
		if(elem->attributes[a].name) free(elem->attributes[a].name);
		if(elem->attributes[a].value) free(elem->attributes[a].value);
	}
	if(elem->attributes) free(elem->attributes);
	if(elem->text)       free(elem->text);
	if(elem->name)       free(elem->name);

	unsigned int i;
        for(i=0; i < elem->children_count; i++) {
                destroy_node(elem->children[i]);
        	elem->children[i] = NULL;
	}
	free(elem->children);
	free(elem);
}

#define LEVEL {unsigned int foo=0; for(foo=0; foo<elem->level; foo++) printf("    ");}

void pretty_print(gNode *elem) {
	if(!elem) {
		printf("elem is %p\n", elem);
		return;
	}

	if(elem->type == ELEM_TEXT) {
		LEVEL printf("%s\n", elem->text);
	} else {
		LEVEL printf("<%s", elem->name);
        unsigned int a;
        for(a = 0; a < elem->attribute_count; a++) {
         	printf(" %s=\"%s\"", elem->attributes[a].name, elem->attributes[a].value);  
        }
        printf(">\n");
	}

	unsigned int i;
	for(i=0; i < elem->children_count; i++) {
		pretty_print(elem->children[i]);
	}

	if(elem->type == ELEM_TEXT) {

	} else {
		LEVEL printf("</%s>\n", elem->name);
	}
}

