#include "ofScraperParser.h"


// super concise and useful !!! 
// http://hamburgsteak.sandwich.net/writ/libxml2.txt


//------------------------------------------------------------------
ofScraperParser::ofScraperParser(){
	ctxt = NULL;
}

//------------------------------------------------------------------		
ofScraperParser::~ofScraperParser(){
	 if (doc != NULL){
	 	xmlFreeDoc(doc);
	 	doc = NULL;
	 }
}

//------------------------------------------------------------------
void ofScraperParser::reset(){
	// free up doc at least...
	if (doc != NULL){
		xmlFreeDoc(doc);
		doc = NULL;
	}
}

//------------------------------------------------------------------
ofScraperXmlNode ofScraperParser::parseHtml (string input){
	
	printf("input %s \n", input.c_str());
    
	// please be careful re: memory here - 
	ofScraperXmlNode node;
	
	// reset context?
	//if (ctxt != NULL){	
		//htmlCtxtReset(ctxt);
	//}
	// get context from html
	ctxt = htmlCreateMemoryParserCtxt (input.c_str(), strlen (input.c_str()));
	if (ctxt != NULL) {
		htmlCtxtUseOptions (ctxt, HTML_PARSE_NOWARNING | HTML_PARSE_NOERROR);
		htmlParseDocument (ctxt);
		doc = ctxt->myDoc;
		xmlNode *root_element = NULL;
		if (doc != NULL && doc->children != NULL){
		   node.myNode = doc->children;
		}
		htmlFreeParserCtxt (ctxt);
	} else {
		printf("null \n");
	}
	//node.print();
	return node;
}



//------------------------------------------------------------------
std::vector<ofScraperXmlNode>  ofScraperParser::getContentOfXpathExpression(ofScraperXmlNode & node, string expression){
	
	
	
	
	// nodes that will be returned:
	std::vector<ofScraperXmlNode> myNodes;
	
	// --------------------------------
	xmlXPathContextPtr xpathCtx; 
    xmlXPathObjectPtr xpathObj; 
    
	
	// --------------------------------
	xpathCtx = xmlXPathNewContext(doc);
	xpathCtx->node = node.myNode;

    if(xpathCtx == NULL) {
        fprintf(stderr,"Error: unable to create new XPath context\n");
        xmlFreeDoc(doc); 
        return myNodes;
    }
    
    
    // --------------------------------
	xpathObj = xmlXPathEvalExpression((unsigned char *)expression.c_str(), xpathCtx);
    if(xpathObj == NULL) {
        fprintf(stderr,"Error: unable to evaluate xpath expression \"%s\"\n", expression.c_str());
        xmlXPathFreeContext(xpathCtx); 
        xmlFreeDoc(doc); 
        return myNodes;
    }

    // --------------------------------
	//print_xpath_nodes(xpathObj->nodesetval, stdout);
	xmlNodeSetPtr nodes = xpathObj->nodesetval;
	xmlNodePtr cur;
	int size;
	FILE * output = stdout;
	size = (nodes) ? nodes->nodeNr : 0;
	//fprintf(output, "Result (%d nodes):\n", size);
	for(int i = 0; i < size; ++i) {
		if (!(nodes->nodeTab[i])){
			printf("here error \n");
		}
		
		if(nodes->nodeTab[i]->type == XML_ELEMENT_NODE) {
		    cur = nodes->nodeTab[i];   	    
		    if(!cur->ns) { 
	    	    
	    	    ofScraperXmlNode tempNode;
	    	    tempNode.myNode = cur;
				myNodes.push_back(tempNode);
	    	    //fprintf(output, "= element node \"%s\"   %s\n", 
			    //cur->name, xmlGetProp( cur, (unsigned char *)"src"));
		    }
		}
	}
	
    // --------------------------------
	xmlXPathFreeObject(xpathObj);
    xmlXPathFreeContext(xpathCtx); 
    //xmlFreeDoc(doc); 
	
	//string result = "";
	//return result;	
	return myNodes;
}
