#include <kdebug.h>
#include <klocale.h>

#include "xpath_query.h"
#include "xpath_expression.h"
#include "xpath_context.h"

namespace XPath {

//
// AxisNode
//

Axis::Axis()
    : XPathNode( AxisNode ),
      id( NullAxis )
{
}

Axis::Axis( const Axis &node )
    : XPathNode( AxisNode ),
      id( node.id )
{
}

Axis::Axis( ushort fid )
    : XPathNode( AxisNode ),
      id( fid )
{
}

Axis::~Axis()
{
}

QString Axis::name() const
{
    const uint names_count = 15;
    const char *names[] = {
	"null_axis",
	"child", "descendent", "parent", "ancestor",
	"following-sibling", "preceding-sibling",
	"following", "preceding",
	"attribute", "namespace",
	"self", "descendent-or-self", "ancestor-or-self",
	"INTERNAL_ERROR"
    };

    if ( id < names_count )
	return QString("%1::").arg( names[id] );
    else
	return QString("axis::id=%1)").arg(id);
}

QString Axis::qstring() const
{
    return name();
}

Value *Axis::evaluate( QueryState */*state*/ )
{
    return new Exception( i18n("TODO: Axis::evaluate()") );
}

//
// BinaryOpNode
//

BinaryOp::BinaryOp()
    : XPathNode( BinaryOpNode ),
      op( NullBinaryOp )
{
}

BinaryOp::BinaryOp( const BinaryOp &node )
    : XPathNode( BinaryOpNode ),
      op( node.op )
{
}

BinaryOp::BinaryOp( ushort bop )
    : XPathNode( BinaryOpNode ),
      op( bop )
{
}

BinaryOp::~BinaryOp()
{
}

QString BinaryOp::name() const
{
    const uint names_count = 14;
    const char *names[] = {
	"null-operator",
	"or", "and", "equality",
	"less-than", "greater-than", "less-than-equal", "greater-than-equal",
	"plus", "minus", "mul", "div", "mod",

	"INTERNAL_ERROR"
    };

    if ( op < names_count )
	return QString("operator %1").arg( names[op] );
    else
	return QString("binop::id=%1)").arg(op);
}

QString BinaryOp::qstring() const
{
    return name();
}

Value *BinaryOp::evaluate( QueryState */*state*/ )
{
    return new Exception( i18n("TODO: BinaryOp::evaluate()") );
}

//
// FunctionCallNode
//

FunctionCall::FunctionCall()
    : XPathNode( FunctionCallNode ),
      id( FunctionNull )
{
}

FunctionCall::FunctionCall( const FunctionCall &node )
    : XPathNode( FunctionCallNode ),
      id( node.id )
{
}

FunctionCall::FunctionCall( ushort fid )
    : XPathNode( FunctionCallNode ),
      id( fid )
{
}

FunctionCall::~FunctionCall()
{
}

QString FunctionCall::name() const
{
    const uint names_count = 29;
    const char *names[] = {
	"null_function",
	"last", "position", "count",
	"id", "local-name", "namespace-uri", "name",
	"string", "concat", "startswith", "contains",
	"substring-before", "substring-after", "substring",
	"string-length", "normalize-space", "translate",
	"boolean", "not", "true", "false", "lang",
	"number", "sum", "floor", "ceiling", "round", "INTERNAL_ERROR"
    };

    if ( id < names_count )
	return QString("%1()").arg( names[id] );
    else
	return QString("function(id=%1)").arg(id);
}

QString FunctionCall::qstring() const
{
    return name();
}

Value *FunctionCall::evaluate( QueryState *state )
{
    switch( id ) {

	// NodeSet functions
	case FunctionLast:
	    return new Number( state->context().size() );
	    break;
	case FunctionPosition:
	    return new Number( state->context().position() );
	    break;
	case FunctionCount:
	    if ( args.count() == 1 ) {
		Value *v = args[0].evaluate( state );
		if ( v->isNodeSet() )
		    return new Number( v->toNodeSet().count() );
	    }
	    return new Exception( i18n("Invalid arguments passed to XPath count().") );
	    break;
	case FunctionId:
	case FunctionLocalName:
	case FunctionNamespaceURI:
	case FunctionName:
	    break;

        // String functions
	case FunctionString:
	case FunctionConcat:
	case FunctionStartsWith:
	case FunctionContains:
	case FunctionSubStringBefore:
	case FunctionSubStringAfter:
	case FunctionSubString:
	case FunctionStringLength:
	case FunctionNormalizeSpace:
	case FunctionTranslate:
	    break;

	// Boolean functions
	case FunctionBoolean:
	case FunctionNot:
	case FunctionTrue:
	case FunctionFalse:
	case FunctionLang:
	    break;

	// Number functions
	case FunctionNumber:
	case FunctionSum:
	case FunctionFloor:
	case FunctionCeiling:
	case FunctionRound:
	    break;

        // Null
	case FunctionNull:
	    return new Exception( i18n("XPath null function called.") );
	    break;
        // Undefined function
	default:
	    return new Exception( i18n("Unknown XPath function (id=%1) called.").arg(id) );
    }

    // Valid, but unimplemented functions
    return new Exception( i18n("XPath function '%1()' (id=%2) is unimplemented.").arg(name()).arg(id) );
}

}; // namespace XPath


// Local Variables:
// c-basic-offset: 4
// End:

