#include <QString>
#include "phpqt_internals.h"

#include "VirtualMethodReturnValue.h"
#include "InvokeSlot.h"

#include <QMetaObject>
#include <QMetaMethod>
#include <QByteArray>
#include "smokephp.h"

#include "marshall_types.h"

// TODO check the second and the 6th argument, its both _id in PHPQt::metacall
InvokeSlot::InvokeSlot(
		Smoke *smoke, 
		const Smoke::Stack stack, 
		const zval* obj, 
		zval **sp, 
		const int slotId, 
		const QMetaObject* metaObject, 
		void** a
) : MethodCallBase( smoke, stack, sp ), 
    _obj(obj), 
    _id(slotId), 
    _metaObject(metaObject), 
    _a(a)
{
    _args = _smoke->argumentList + method().args;

    // break at the first '('
    QByteArray signature( _metaObject->method(_id).signature() );
    _slotName.append( signature.left( signature.indexOf("(") ) );

    QList<QByteArray> qargs = _metaObject->method(_id).parameterTypes();
    _items = qargs.count();
    _mocStack = new MocArgument[ _items + 1 ];
    smokephp_QtToMoc(_a + 1, qargs, _mocStack);
    smokeStackFromQtStack(_stack, _a + 1, _items, _mocStack);
}

InvokeSlot::~InvokeSlot()
{
}

Marshall::Action
InvokeSlot::action()
{
	return Marshall::ToZVAL;
}

zval*
InvokeSlot::var()
{
	MethodCallBase::_sp[_cur] = (zval*) emalloc(sizeof(zval));
    return MethodCallBase::_sp[_cur];
}

const int
InvokeSlot::items()
{
    return _items;
}

void
InvokeSlot::callMethod()
{
    if (_called) return;
    _called = true;
    zval* retval = PHPQt::callPHPMethod(_obj, _slotName.constData(), items(), MethodCallBase::_sp);
//    if(_args[0].argType != xmoc_void)
	VirtualMethodReturnValue r(_smoke, _method, _stack, retval);
}

bool
InvokeSlot::cleanup()
{
	return false;
}

bool
InvokeSlot::callable(const zend_class_entry* ce)
{
    return PHPQt::methodExists(ce, _slotName.constData());
}

SmokeType
InvokeSlot::type()
{
    return _mocStack[_cur].st;
}

Smoke::StackItem &
InvokeSlot::item()
{
    return _stack[_cur];   
}
