/*
	ZXMLReader.hpp
	Author: James Russell <jcrussell@762studios.com>
	Created: 5/11/2012

	Purpose: 

	Reads in data from the given XML input and parses the data into a ZKVTree instance 
	that can be used for path-based lookup and iteration of values.  For example, the following
	XML data:

	<node type="emitter">
	  <position x="100" y="100" z="1" />
	  <facing x="0" y="0" z="1" />

	  This is a particle emitter node.
    </node>
	<node type="time" value="2200" />

	Is given the following ZKVTree layout (node values in parenthesis):

	Root 
	|
	+-> node (This is a particle emitter node.)
	|   |
	|   +-> type (emitter)
	|   |
	|   +-> position ()
	|   |   |
	|   |   +-> x (100)
	|   |   +-> y (100)
	|   |   +-> z (1)
	|   | 
	|   +-> facing ()
	|   |   |
	|       +-> x (0)
	|		+-> y (0)
	|	    +-> z (1)
	|
	+-> node
	    |
		+-> type (time)
		+-> value (2200)

	Note that all XML elements will have the body assigned to the value of the node.  Attributes 
	will have their attribute value assigned to the node value, but will never have child nodes.

	This does mean that an XML element with a body value but no attributes will be functionally
	identical in the KVTree representation to an attribute of the parent element.  For example, the 
	following two XML snippets will have an identical layout in the KVTree:

	<node type="emitter">
		<flags>1</flags>
	</node>

	<node type="emitter" flags="1" />

	The parsed layout in ZKVTree form is as follows:

	Root 
	|
	+-> node ()
	    |
	    +-> type (emitter)
	    |
	    +-> flags (1)

	Note that the current implementation uses rapidxml, and will technically parse a superset of W3C
	compliant XML as valid.  In particular, closing tags are not checked for matching, meaning that
	any closing tag will close any node.  There are other non-W3C compliance issues with rapidxml
	as well, although it will never refuse to parse valid XML.

	More information about rapidxml can be found here: http://rapidxml.sourceforge.net/manual.html

	License:

	TODO

*/

#pragma once

#ifndef _ZXMLREADER_HPP
#define _ZXMLREADER_HPP

#include <ZUtil/ZKVTree.hpp>
#include <ZUtil/ZSmartPointer.hpp>

/*
ZXMLReader class, which converts XML data into a ZKVtree that can be used to access / iterate
the data.
*/
class ZXMLReader
{
public:
	/*
	Default Constructor.
	*/
	ZXMLReader()
		: ErrorMessage() { } 

	/*
	Destructor.
	*/
	~ZXMLReader() 
		{ Tree.Clear(); }

	
	/*
	public ZXMLReader::Read

	Reads in XML data stored as a ZString and parses it into an internal format.
	
	@param _xml - Pointer to XML data
	@return (bool) - true if successful, false if failure (use GetErrorString() to get the message)
	*/
	bool Read(const ZString& _xml)
		{ return Read(_xml.Data(), _xml.Length()); }

	/*
	public ZXMLReader::Read

	Reads in XML data stored as a memory block and parses it into an internal format.
	
	@param _data - Pointer to XML data
	@param _length - Length of XML data
	@return (bool) - true if successful, false if failure (use GetErrorString() to get the message)
	*/
	bool Read(const char* _data, size_t _length);

	/*
	public ZXMLReader::GetErrorString

	Gets the error message generated while loading the data if loading failed.  If loading
	the data was successful, this returns an empty string.

	@return (const ZString&) - error message string
	*/
	const ZString& GetErrorString();

	/*
	public ZXMLReader::GetKVTree

	Gets the data from the parsed XML as a key-value tree.  If the loading failed,
	the tree is returned empty.



	@param _kvtree - the tree to fill with parsed xml data
	*/
	void GetKVTree(ZKVTree& _kvtree);

private:
	DISABLE_COPY_AND_ASSIGN(ZXMLReader);

	ZString ErrorMessage;	// error message (if there has been an error)	
	ZKVTree Tree;			// tree to store the xml in
};

#endif
