/*!
 * PHP-Qt - The PHP language bindings for Qt
 *
 * Copyright (C) 2006 - 2007
 * Thomas Moenicke <tm at php-qt.org>
 * Katrina Niolet <katrina at niolet.name>
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 */

#ifndef QTPHP_H
#define QTPHP_H

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

#define PHPQT_VERSION "0.9"
#define QIDI_VERSION "0.1"
#define QSTRING_CLASSID -1 // QString is not in smoke
#define COMPILE_DL_PHP_QT

#include <php.h>
#include <php_ini.h>
//#include <QMultiMap>

class QMetaObject;

#define Qnil (zval *) NULL

void init_codec();
zval* zstringFromQString(QString * s);

class smokephp_object {
public:
	inline smokephp_object(Smoke* smoke, const int classId, const void* ptr, const zend_class_entry* ce, zval* zval_ptr)
		: 	m_smoke(smoke),
			m_classId(classId),
			m_ptr(ptr),
			m_ce_ptr(ce),
			m_parent_ce_ptr(ce),
			m_zval_ptr(zval_ptr),
			m_allocated( false ),
			m_meta(0),
			m_handle(zval_ptr->value.obj.handle)
	{
//		m_SignalSlot = new QMultiMap<QString, QString>;
	}

	inline const bool allocated() { return m_allocated; }
	inline Smoke* smoke() { return m_smoke; }
	inline const int classId() { return m_classId; }
	inline const void* ptr() { return m_ptr; }
	inline void* mPtr() { return const_cast<void*>(m_ptr); } // can be modified
	inline const zend_class_entry* ce_ptr() { return m_ce_ptr; }
	inline const zend_class_entry* parent_ce_ptr() { return m_parent_ce_ptr; }
	inline const zval* zval_ptr() { return m_zval_ptr; }
	inline const QMetaObject* meta() { return m_meta; }
	inline const QString className() { return QString(ce_ptr()->name); }
	inline const zend_object_handle handle(){ return m_handle; }

	inline void setAllocated( bool allocated ) { m_allocated = allocated; }
	inline void setParentCePtr(zend_class_entry* parent_ce_ptr) { m_parent_ce_ptr = parent_ce_ptr; }
	inline void setMetaObject(const QMetaObject* meta) { m_meta = meta; }
	inline void setPtr(void* ptr) { m_ptr = ptr; }
	inline void setZvalPtr(zval* z){ m_zval_ptr=z; }

private:
	bool m_allocated; // true means ownership by bindings, Qt else
    Smoke *m_smoke;
    int m_classId;
    const void *m_ptr;
    const zend_class_entry *m_ce_ptr;
    const zend_class_entry *m_parent_ce_ptr;
    zval *m_zval_ptr;
    const QMetaObject* m_meta;
//    QMultiMap<QString,QString> *m_SignalSlot;
    const zend_object_handle m_handle;
};

// singleton that wraps the current smoke object
extern Smoke* qt_Smoke;
class PQ
{
private:
    PQ();
    PQ(const PQ& cc){}

public:
    ~PQ();
    static inline Smoke* smoke() { return qt_Smoke; }

	typedef short Index;

	static inline const char* findRealMethodName(const char* methodName)
	{

		if(!methodName) return "";
		QString _m(methodName);
		//! TODO its slow but safe, implement a better algorithm
		for(Index i=0; i < PQ::smoke()->numMethodNames; i++){
			if(_m.compare(PQ::smoke()->methodNames[i], Qt::CaseInsensitive) == 0){ return PQ::smoke()->methodNames[i]; }
		}
		qFatal("PQ::findRealMethodName(): could not find %s", methodName);
	}

};

#endif
