/*
 *  Copyright (C) 2003, Richard J. Moore <rich@kde.org>
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library 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
 *  Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public License
 *  along with this library; see the file COPYING.LIB.  If not, write to
 *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 *  Boston, MA 02110-1301, USA.
 */
#include "kjsembed/jsbinding.h"
#include "saxhandler.h"

namespace KJSEmbed {
namespace BuiltIns {

SaxHandler::SaxHandler( KJS::ExecState *execstate )
    : TQXmlDefaultHandler(), exec(execstate), error( ErrorNone )
{
}

SaxHandler::~SaxHandler()
{
}

void SaxHandler::setHandler( const KJS::Object &handler )
{
    jshandler = handler;
}

bool SaxHandler::startDocument()
{
    if ( !jshandler.isValid() ) {
	error = ErrorNoHandler;
	return false;
    }

    KJS::Identifier funName("startDocument");
    if ( !jshandler.hasProperty(exec, funName) )
	return TQXmlDefaultHandler::startDocument();

    KJS::Object fun = jshandler.get(exec, funName).toObject( exec );
    if ( !fun.implementsCall() ) {
	error = ErrorNotCallable;
	return false;
    }

    KJS::Value ret = fun.call( exec, jshandler, KJS::List() );
    return ret.toBoolean( exec );
}

bool SaxHandler::endDocument()
{
    if ( !jshandler.isValid() ) {
	error = ErrorNoHandler;
	return false;
    }

    KJS::Identifier funName("endDocument");
    if ( !jshandler.hasProperty(exec, funName) )
	return TQXmlDefaultHandler::endDocument();

    KJS::Object fun = jshandler.get(exec, funName).toObject( exec );
    if ( !fun.implementsCall() ) {
	error = ErrorNotCallable;
	return false;
    }

    KJS::Value ret = fun.call( exec, jshandler, KJS::List() );
    return ret.toBoolean( exec );
}

bool SaxHandler::startElement( const TQString &ns, const TQString &ln, const TQString &qn,
			       const TQXmlAttributes &attrs )
{
    if ( !jshandler.isValid() ) {
	error = ErrorNoHandler;
	return false;
    }

    KJS::Identifier funName("startElement");
    if ( !jshandler.hasProperty(exec, funName) )
	return TQXmlDefaultHandler::startElement( ns, ln, qn, attrs );

    KJS::Object fun = jshandler.get(exec, funName).toObject( exec );
    if ( !fun.implementsCall() ) {
	error = ErrorNotCallable;
	return false;
    }

    KJS::List args;
    args.append( KJS::String(ns) );
    args.append( KJS::String(ln) );
    args.append( KJS::String(qn) );
    // TODO: XmlAttributes not yet supported

    KJS::Value ret = fun.call( exec, jshandler, args );
    return ret.toBoolean( exec );
}

bool SaxHandler::endElement( const TQString &ns, const TQString &ln, const TQString &qn )
{
    if ( !jshandler.isValid() ) {
	error = ErrorNoHandler;
	return false;
    }

    KJS::Identifier funName("endElement");
    if ( !jshandler.hasProperty(exec, funName) )
	return TQXmlDefaultHandler::endElement( ns, ln, qn );

    KJS::Object fun = jshandler.get(exec, funName).toObject( exec );
    if ( !fun.implementsCall() ) {
	error = ErrorNotCallable;
	return false;
    }

    KJS::List args;
    args.append( KJS::String(ns) );
    args.append( KJS::String(ln) );
    args.append( KJS::String(qn) );

    KJS::Value ret = fun.call( exec, jshandler, args );
    return ret.toBoolean( exec );
}

bool SaxHandler::characters( const TQString &chars )
{
    if ( !jshandler.isValid() ) {
	error = ErrorNoHandler;
	return false;
    }

    KJS::Identifier funName("characters");
    if ( !jshandler.hasProperty(exec, funName) )
	return TQXmlDefaultHandler::characters( chars );

    KJS::Object fun = jshandler.get(exec, funName).toObject( exec );
    if ( !fun.implementsCall() ) {
	error = ErrorNotCallable;
	return false;
    }

    KJS::List args;
    args.append( KJS::String(chars) );

    KJS::Value ret = fun.call( exec, jshandler, args );
    return ret.toBoolean( exec );
}

TQString SaxHandler::errorString()
{
    switch( error ) {

	case ErrorNoHandler:
	    return TQString("No handler specified");
	    break;
	case ErrorNotCallable:
	    return TQString("One of the callbacks of the handler is not callable");
	    break;
	case ErrorNone:
	    // This only means that no error occured in the JS dispatch, there
	    // could still have been an error from the parser so we fall
	    // though to call the baseclass.
	    break;
	default:
	    break;
    }

    return TQXmlDefaultHandler::errorString();
}

} // namespace KJSEmbed::BuiltIns
} // namespace KJSEmbed
