/*****
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *****/


//#include "stdafx.h"
#include "xml.h"
#include <stdio.h>
#include <algorithm>
#include "Exception.h"

//#ifdef _DEBUG
//#define new DEBUG_NEW
//#endif

namespace XML 
{

//------------------------------------------------------
// Node
//------------------------------------------------------

template <class T>
void my_delete(T& v) { delete v; v = NULL; }

Node::~Node()
{
	std::for_each(m_child.begin(), m_child.end(), my_delete<Node*>);
}

Node *Node::allocNode(TiXmlElement *tnode)
{
	Node *node = new Node(tnode);
	m_child.push_back(node);
	return node;
}


int Node::asInteger() const
{
	if (!m_node) return 0;
	TiXmlElement *e = m_node->ToElement();
	if (!e) return 0;
	const char *s = e->GetText();
	if (!s) return 0;

	int data=0;
	std::string _data(s);
	if( _data.find( "0x" ) == 0 )	{
		data = strtol( _data.substr( 2, _data.length() - 2 ).c_str(), 0, 16 );
	} else {
		data = atoi( _data.c_str() );
	}

	return data;
}

bool Node::asBool() const
{
	if (!m_node) return false;
	TiXmlElement *e = m_node->ToElement();
	if (!e) return false;

	const char *s = e->GetText();
	if (!s) return false;
	
	return strstr(s, "1") || _stricmp(s, "true")==0;
}

std::string Node::asString() const
{
	if (!m_node) return "";
	TiXmlElement *e = m_node->ToElement();
	if (!e) return "";
	const char *s = e->GetText();

	return s ? s : "";
}

float Node::asFloat () const
{
	if (!m_node) return 0.0f;
	TiXmlElement *e = m_node->ToElement();
	if (!e) return 0.0f;
	const char *s = e->GetText();

	return s ? atof(s) : 0.0f;
}

Node *Node::findNode( const std::string &name, int index, bool raiseError )
{
	if (m_node) 
	{
		int found = 0;
		TiXmlElement *node = m_node->FirstChildElement(name);
		while (node)
		{
			if (found==index) 
				return allocNode(node);

			node = node->NextSiblingElement(name);

			found++;
		}

		if (raiseError)
			THROWXMLEXCEPTION("Node was not found.");
	}

	return NULL;
}

bool Node::lookupAttribute( const std::string &name, unsigned int &data ) const
{
	if (!m_node) return false;
	TiXmlElement *e = m_node->ToElement();
	if (!e) return false;

	const char *s = e->Attribute(name.c_str());
	if (!s) return false;

	std::string value(s);

    if ( value.substr(0,1) == "#")
        data = strtol( value.substr( 1, value.length() - 1 ).c_str(), 0, 16 );
	else if ( value.find( "0x" ) == 0 )
		data = strtol( value.substr( 2, value.length() - 2 ).c_str(), 0, 16 );
	else
		data = atoi( value.c_str() );

	return true;
}

bool Node::lookupAttribute( const std::string &name, int &data ) const
{
	if (!m_node) return false;
	TiXmlElement *e = m_node->ToElement();
	if (!e) return false;

	const char *s = e->Attribute(name.c_str());
	if (!s) return false;

	std::string value(s);

    if ( value.substr(0,1) == "#")
        data = strtol( value.substr( 1, value.length() - 1 ).c_str(), 0, 16 );
	else if ( value.find( "0x" ) == 0 )
		data = strtol( value.substr( 2, value.length() - 2 ).c_str(), 0, 16 );
	else
		data = atoi( value.c_str() );

	return true;
}

bool Node::lookupAttribute( const std::string &name, std::string &data ) const
{
	if (!m_node) return false;
	TiXmlElement *e = m_node->ToElement();
	if (!e) return false;

	const char *s = e->Attribute(name.c_str());
	if (!s) return false;

	data = s;

	return true;
}

std::string Node::findString (const std::string & name)
{
	Node *node = findNode (name);
	if (node)
		return node->asString ();
	else
		return "";
}

int Node::findInteger (const std::string & name)
{
	Node *node = findNode (name);
	if (node)
		return node->asInteger ();
	else
		return 0;
}

float Node::findFloat (const std::string & name)
{
	Node *node = findNode (name);
	if (node)
		return node->asFloat ();
	else
		return 0.0f;
}

#if 0
int Node::asInteger() const
{
	if (!m_node) return 0;
	std::string _data = m_node->ValueStr();

	int data=0;
	if( _data.find( "0x" ) == 0 )	{
		data = strtol( _data.substr( 2, _data.length() - 2 ).c_str(), 0, 16 );
	} else {
		data = atoi( _data.c_str() );
	}

	return data;
}

const std::string & Node::asString() const 
{
	return m_node ? m_node->ValueStr() : "";
}

bool Node::asBool() const
{
	if (!m_node) return false;
	std::string _data = m_node->ValueStr();

	if(_data.find('1') != std::string::npos) return 1;
	if(_data == "true") return 1;
	return 0;
}
#endif


//------------------------------------------------------
// Parser
//------------------------------------------------------


Node *Parser::parseDocument()
{
	Node *result = new Node(&m_doc);

	return result;
}

void Parser::setData( const std::string &data )
{
	
}

Parser::~Parser()
{
}

void Parser::loadData( const std::string &filename )
{
	if (!m_doc.LoadFile(filename))
		reportError(m_doc.ErrorDesc());
}

void Parser::reportError(const std::string &error)
{
	THROWXMLEXCEPTION(error);
}


}
