/*
 *  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., 59 Temple Place - Suite 330,
 *  Boston, MA 02111-1307, USA.
 */

#include <qvariant.h>
#include "global.h"

#include "jsfactory.h"
#include "jseventmapper.h"
#include "jsobjectproxy.h"
#include "kjsembedpart.h"
#include "jsbinding.h"

#include "jsobjecteventproxy.h"
#ifndef QT_ONLY
#include "jsobjecteventproxy.moc"
#endif // QT_ONLY

namespace KJSEmbed {

// We'll need to increase this if we need to support any custom events
static const QEvent::Type QEVENT_TYPE_MAX = QEvent::TabletRelease;

JSObjectEventProxy::JSObjectEventProxy( JSObjectProxy *parent, const char *name )
    : QObject( parent->object(), name ? name : "jsobjecteventproxy" ),
      proxy( parent ), eventMask( QEVENT_TYPE_MAX ), refcount(0)
{
    eventMask.fill( false );
}

JSObjectEventProxy::~JSObjectEventProxy()
{
}

bool JSObjectEventProxy::isFiltered( QEvent::Type t ) const
{
    return eventMask.testBit( t );
}

void JSObjectEventProxy::addFilter( QEvent::Type t )
{
    if ( !refcount )
	proxy->object()->installEventFilter( this );

    if ( !eventMask.testBit(t) ) {
	refcount++;
	eventMask.setBit( t );
    }

    kdDebug(80001) << "JSObjectEventProxy::addFilter done" << endl;
}

void JSObjectEventProxy::removeFilter( QEvent::Type t )
{
    eventMask.clearBit( t );
    refcount--;
    if ( !refcount ) {
	proxy->object()->removeEventFilter( this );
	deleteLater();
    }
}

bool JSObjectEventProxy::eventFilter( QObject */*watched*/, QEvent *e )
{
    if ( isFiltered(e->type()) )
	callHandler( e );

    return false;
}

KJS::Value JSObjectEventProxy::callHandler( QEvent *e )
{
// Be careful enabling this as if there are a lot of events then the event loop times
// out and the app crashes with 'Alarm Clock'.
//    kdDebug(80001) << "JSObjectEventProxy::callHandler() event type " << e->type() << endl;

    KJS::ExecState *exec = proxy->interpreter()->globalExec();
    KJS::Identifier *id = proxy->part()->factory()->eventMapper()->findEventHandler( e->type() );
    KJS::Object jsobj( proxy );
    KJS::Object fun = jsobj.get(exec, *id ).toObject( exec );

    if ( !fun.implementsCall() ) {
	kdDebug(80001) << "bad event handler for type " << e->type() << endl;
	return KJS::Boolean(false);
    }

    // Process args
    KJS::List args;
    KJS::Object obj = proxy->part()->factory()->createProxy( exec, e, proxy );
    args.append( obj );

    return fun.call( exec, jsobj, args );
}

} // KJSEmbed


