#include "ofXML.h"


ofXML::ofXML(){
	mainTagSet		= false;
	readingEnabled	= false;
	verbose			= true;
}

//---------------------------------------------------------
void ofXML::setVerbose(bool _verbose)
{
	verbose = _verbose;
}

//---------------------------------------------------------

void ofXML::init(char * mainTag)
{
	xMainNode		= XMLNode::createXMLTopNode(mainTag);
	mainTagSet		= true;
	readingEnabled	= false;
}

//---------------------------------------------------------

void ofXML::initFromFile(char * xmlFile, char * mainTag)
{

	mainTagSet		= true;
	
    //open and parse the XML file:
	xMainNode=XMLNode::openFileHelper(xmlFile,mainTag);
		
	if(!xMainNode.isError){
		//all is good we can read the file
		readingEnabled = true;
		if(verbose)printf("ofXML:  opening file %s \n", xmlFile);
	}
	else{
		//we create a node for file writing only
		if(verbose)printf("ofXML:  file not found or main tag missing - creating for file writing only\n");
		xMainNode		= XMLNode::createXMLTopNode(mainTag);
		readingEnabled	= false;
	}
}

//---------------------------------------------------------
void ofXML::saveFile(char * xmlFile)
{
	if(!mainTagSet){
		if(verbose)printf("ofXML:  mainTag not set, please set with init() or initFromFile()\n");
		return;
	}
	if(verbose)printf("ofXML:  saving file %s \n", xmlFile);
	xMainNode.writeToFile(xmlFile);
}

//---------------------------------------------------------
void ofXML::clearTagContents(char * tag)
{
	//This empties all elements inside a tag.
	//Can be used for clearing just the text
	//or for the child structures.
	XMLNode myNode = parseTag(tag);
	if(myNode.getName() != NULL)myNode.deleteNodeContent(true);
}

//---------------------------------------------------------
void ofXML::removeTag(char * tag)
{
	//kind of ghetto way to remove a tag
	//we set its name to "" 
	//seems to work. This is in lui of 
	//not having a remove tag command
	XMLNode myNode = parseTag(tag);
	if(myNode.getName() != NULL){
		clearTagContents(tag);
		myNode.updateName("");
	}
}

//---------------------------------------------------------
void ofXML::getValue(char * tag, int * valueAsInt)
{
	if( checkErrors() )return;

	if(!mainTagSet){
		if(verbose)printf("ofXML:  mainTag not set, please set with init() or initFromFile()\n");
		return;
	}
	
	XMLNode myNode = this->parseTag(tag); 

	//Added this to the XML Parser class
	//Returns true if the tag contains any text
	if( myNode.isText() ){
		//This only modifies the int if there is a value
		//So you can pass in a default value and it will
		//be not affected if no value can be found.
		*valueAsInt = atoi( myNode.getText() );
	}
	else{
		if(verbose)printf("ofXML:  tag %s not found value set to %i\n", tag, *valueAsInt);
	}
}

//---------------------------------------------------------

void ofXML::getValue(char * tag, float * valueAsFloat)
{
	if( checkErrors() )return;

	XMLNode myNode = this->parseTag(tag); 
	
	//Added this to the XML Parser class
	//Returns true if the tag contains any text
	if( myNode.isText() ){
		//This only modifies the float if there is a value
		//So you can pass in a default value and it will
		//be not affected if no value can be found.
		*valueAsFloat = atof( myNode.getText() );
	}else{
		if(verbose)printf("ofXML:  tag %s not found value set to %f\n", tag,  *valueAsFloat);
	}
}

//---------------------------------------------------------

void ofXML::getValue(char * tag, char * valueAsString)
{
	if( checkErrors() )return;

	XMLNode myNode = this->parseTag(tag); 
	
	//Added this to the XML Parser class
	//Returns true if the tag contains any text
	if( myNode.isText() ){
		//Warning you better pass in buffer large enough!!!
		//You need size of string you are getting +1
		//otherwise boom explosion!
		int sizeOfString = strlen(myNode.getText());
		
		memset(valueAsString, 0, sizeOfString+1); //So the string is terminated
		memcpy(valueAsString, myNode.getText(), sizeOfString);
		
	}else{
		if(verbose)printf("ofXML:  tag %s not found value set to %f\n", tag,  *valueAsString);
	}
}



//---------------------------------------------------------

void ofXML::setValue(char * tag, int value)
{
	char tmpStr[512];
	memset(tmpStr, 0, 512);
	
	sprintf(tmpStr,"%i",value); 
	setValue(tag, tmpStr);
}

//---------------------------------------------------------

void ofXML::setValue(char * tag, float value)
{
	char tmpStr[512];
	memset(tmpStr, 0, 512);
	
	sprintf(tmpStr,"%f",value); 
	setValue(tag, tmpStr);
}


//---------------------------------------------------------

void ofXML::setValue(char * tag, char * value)
{
	//Now that a value has been set we def have something to read
	readingEnabled = true;

	if(!mainTagSet){
		if(verbose)printf("ofXML:  mainTag not set, please set with init() or initFromFile()\n");
		return;
	}

	XMLNode xNode;
	
	int pos		= 0;
	int index	= 0;
	bool first	= true;
	char * ptr  = tag;

	//Parse through the text one
	//char at a time
	while(tag[index] != 0){
		
		//look for the seperator
		if(tag[index] == ':'){
			//create a tmp string to store the tag name
			char * str = new char[pos+1];
			memset(str, 0, pos+1); //This is to make sure the str is terminated
			memcpy(str, ptr, pos);
			//if(verbose)printf("tag is %s ptr is %s pos is  %i\n", str, ptr, pos);
			
			//If this is the first tag
			//we need to reference the 
			//main node 
			if(first){
				xNode = xMainNode.getChildNode(str);	
				first = false;
				
				//If we are empty and have no text
				//then we don't exist.
				//if( xNode.isEmpty() && !xNode.isText() )	
				
				if( xNode.getName() == NULL ){
					xMainNode.addChild(str);
				}
				
				xNode = xMainNode.getChildNode(str);	
			}
			else{
				
				//If we are empty and have no text
				//then we don't exist.
				//So let us create a new node
				//Might have to check for nodes with
				//no text.
				
				if( xNode.getChildNode(str).getName() == NULL )	{
					xNode.addChild(str);
				}
		
				xNode = xNode.getChildNode(str);
			}
			//destroy the tmp string
			delete str;	
						
			//Make sure our tag ptr is now pointing
			//at the begining of the next tag
			ptr+=pos+1;
			pos = 0;	
		}
		else pos++;
		index++;
	}
	
	//Finally grab the last tag in the structure
	//which is the one we actually want to write
	//to
			
	//it could be the first tag ie "Red"
	//or it could be a child tag ie "Color:Red"
	//so we check
	if(first){
		xNode = xMainNode.getChildNode(ptr);
		if( xNode.getName() == NULL ){
			xMainNode.addChild(ptr);
		}
		xNode = xMainNode.getChildNode(ptr);
	}
	else{
		if( xNode.getChildNode(ptr).getName() == NULL ){
			xNode.addChild(ptr);
		}
		xNode = xNode.getChildNode(ptr);
	}
	
    xNode.updateText(value);  
}

//---------------------------------------------------------

XMLNode ofXML::parseTag(char * tag)
{
	
	//This is where we parse the tag.
	//We make sure that non-
	//existant tags don't crash the 
	//system. 
	
	//Tags can be in the format TAG
	//Representing <TAG>some text</TAG>
	
	//Or they can be in the format 
	//MainTag:InnerTag:Color:RED
	//Representing 
	/*
		<MainTag>
				<InnerTag>
					<Color>
						<RED>
							Some Value here
						</RED>
					</Color>
				</InnerTag>
		</MainTag>
	*/			
						
	XMLNode xNode;
	
	int pos		= 0;
	int index	= 0;
	bool first	= true;
	char * ptr  = tag;

	//Parse through the text one
	//char at a time
	while(tag[index] != 0){
		
		//look for the seperator
		if(tag[index] == ':'){
			//create a tmp string to store the tag name
			char * str = new char[pos+1];
			memset(str, 0, pos+1); //This is to make sure the str is terminated
			memcpy(str, ptr, pos);
			//if(verbose)printf("tag is %s ptr is %s pos is  %i\n", str, ptr, pos);
			
			//If this is the first tag
			//we need to reference the 
			//main node 
			if(first){
				xNode = xMainNode.getChildNode(str);
				first = false;
			}
			else{
				//Otherwise we get the child node
				xNode = xNode.getChildNode(str);
			}
			//destroy the tmp string
			delete str;				
			
			//Make sure our tag ptr is now pointing
			//at the begining of the next tag
			ptr+=pos+1;
			pos = 0;	
			
			//If the tag is empty then 
			//we should stop
			if( xNode.isEmpty() ) break;
		}
		else pos++;
		index++;
	}
	
	//Finally grab the last tag in the structure
	//which is the one we actually want to get the
	//contents of.
	
	//it could be the first tag ie "Red"
	//or it could be a child tag ie "Color:Red"
	//so we check
	if(first)xNode = xMainNode.getChildNode(ptr);
	else xNode = xNode.getChildNode(ptr);
	
	//finally we return the node
	//it might not contain anything or even exist
	//we do checking outside of this function
	//before using it
	return xNode;	
}

//---------------------------------------------------------

bool ofXML::checkErrors()
{
	if(!mainTagSet){
		if(verbose)printf("ofXML:  mainTag not set, please set with init() or initFromFile()\n");
		return true;
	}

	if(!readingEnabled){
		if(verbose)printf("ofXML:  nothing to read. either: no value set / file missing / file empty\n");
		return true;
	}
	
	return false;
}
































//WARNING this relies on you passing a string large enough to 
//handle the value.
/*void ofXML::getValue(char * tag, char * valueAsString)
{	


}



//OLD PARSING CODE
//char str[512];
	
	XMLNode xNode;
	bool first = true;
	
	int c = 0;
	int index = 0;
	
	char * ptr = tag;
	while(tag[index] != 0){
	
		if(tag[index] == ':'){
	
			char tmp[c];
			memcpy(tmp, str, c);
	
			if(verbose)printf("str is %s \n", tmp);
	
			if(first==true){
				xNode = xMainNode.getChildNode(tmp);
				if( xNode.isEmpty() ) return;
			}
			else{
				xNode = xNode.getChildNode(tmp);
			}
			
			if( xNode.isEmpty() ) return;
			
			ptr+= c+1;
			c = 0;
		}
		else
		{
			str[c] = tag[index];
			c++;
		}
		
		index++;
	}
		
	if(verbose)printf("attempting to get %s %i\n", ptr, c);
	
	if(first)xNode = xMainNode.getChildNode(ptr);
	else xNode = xNode.getChildNode(ptr);
		
	memcpy( valueAsString, xNode.getText(),  strlen( xNode.getText() ) );



*/

