/*
 * Copyright (C) 2006 Trolltech ASA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#include "config.h"
#include "identifier.h"

#include "qt_class.h"
#include "qt_instance.h"
#include "qt_runtime.h"

#include <qmetaobject.h>
#include <qdebug.h>

namespace KJS {
namespace Bindings {

QtClass::QtClass(const QMetaObject* mo)
    : m_metaObject(mo)
{
}

QtClass::~QtClass()
{
}

typedef HashMap<const QMetaObject*, QtClass*> ClassesByMetaObject;
static ClassesByMetaObject* classesByMetaObject = 0;

QtClass* QtClass::classForObject(QObject* o)
{
    if (!classesByMetaObject)
        classesByMetaObject = new ClassesByMetaObject;

    const QMetaObject* mo = o->metaObject();
    QtClass* aClass = classesByMetaObject->get(mo);
    if (!aClass) {
        aClass = new QtClass(mo);
        classesByMetaObject->set(mo, aClass);
    }

    return aClass;
}

const char* QtClass::name() const
{
    return m_metaObject->className();
}

// We use this to get at signals (so we can return a proper function object,
// and not get wrapped in RuntimeMethod).  Also, use this for methods,
// so we can cache the JSValue* and return the same JSValue for the same
// identifier...
//
// Unfortunately... we need to gcProtect our JSValues, since we don't have
// access to an actual JS class that can mark() our JSValues.
//
JSValue* QtClass::fallbackObject(ExecState *exec, Instance *inst, const Identifier &identifier)
{
    QtInstance* qtinst = static_cast<QtInstance*>(inst);

    QByteArray name(identifier.ascii());

    // First see if we have a cache hit
    JSValue* val = qtinst->m_methods.value(name);
    if (val)
        return val;

    // Nope, create an entry
    QByteArray normal = QMetaObject::normalizedSignature(name.constData());

    // See if there is an exact match
    int index = -1;
    if (normal.contains('(') && (index = m_metaObject->indexOfMethod(normal)) != -1) {
        QMetaMethod m = m_metaObject->method(index);
        if (m.access() != QMetaMethod::Private) {
            JSValue *val = new QtRuntimeMetaMethod(exec, identifier, static_cast<QtInstance*>(inst), index, normal, false);
            gcProtect(val);
            qtinst->m_methods.insert(name, val);
            return val;
        }
    }

    // Nope.. try a basename match
    int count = m_metaObject->methodCount();
    for (index = count - 1; index >= 0; --index) {
        const QMetaMethod m = m_metaObject->method(index);
        if (m.access() == QMetaMethod::Private)
            continue;

        QByteArray signature = m.signature();
        signature.truncate(signature.indexOf('('));

        if (normal == signature) {
            JSValue* val = new QtRuntimeMetaMethod(exec, identifier, static_cast<QtInstance*>(inst), index, normal, false);
            gcProtect(val);
            qtinst->m_methods.insert(name, val);
            return val;
        }
    }

    return jsUndefined();
}

// This functionality is handled by the fallback case above...
MethodList QtClass::methodsNamed(const Identifier&, Instance*) const
{
    return MethodList();
}

// ### we may end up with a different search order than QtScript by not
// folding this code into the fallbackMethod above, but Fields propagate out
// of the binding code
Field* QtClass::fieldNamed(const Identifier& identifier, Instance* instance) const
{
    // Check static properties first
    QtInstance* qtinst = static_cast<QtInstance*>(instance);

    QObject* obj = qtinst->getObject();
    UString ustring = identifier.ustring();
    QString objName(QString::fromUtf16((const ushort*)ustring.rep()->data(),ustring.size()));
    QByteArray ba = objName.toAscii();

    // First check for a cached field
    QtField* f = qtinst->m_fields.value(objName);

    if (obj) {
        if (f) {
            // We only cache real metaproperties, but we do store the
            // other types so we can delete them later
            if (f->fieldType() == QtField::MetaProperty)
                return f;
            else if (f->fieldType() == QtField::DynamicProperty) {
                if (obj->dynamicPropertyNames().indexOf(ba) >= 0)
                    return f;
                else {
                    // Dynamic property that disappeared
                    qtinst->m_fields.remove(objName);
                    delete f;
                }
            } else {
                QList<QObject*> children = obj->children();
                for (int index = 0; index < children.count(); ++index) {
                    QObject *child = children.at(index);
                    if (child->objectName() == objName)
                        return f;
                }

                // Didn't find it, delete it from the cache
                qtinst->m_fields.remove(objName);
                delete f;
            }
        }

        int index = m_metaObject->indexOfProperty(identifier.ascii());
        if (index >= 0) {
            QMetaProperty prop = m_metaObject->property(index);

            if (prop.isScriptable(obj)) {
                f = new QtField(prop);
                qtinst->m_fields.insert(objName, f);
                return f;
            }
        }

        // Dynamic properties
        index = obj->dynamicPropertyNames().indexOf(ba);
        if (index >= 0) {
            f = new QtField(ba);
            qtinst->m_fields.insert(objName, f);
            return f;
        }

        // Child objects

        QList<QObject*> children = obj->children();
        for (index = 0; index < children.count(); ++index) {
            QObject *child = children.at(index);
            if (child->objectName() == objName) {
                f = new QtField(child);
                qtinst->m_fields.insert(objName, f);
                return f;
            }
        }

        // Nothing named this
        return 0;
    } else {
        QByteArray ba(identifier.ascii());
        // For compatibility with qtscript, cached methods don't cause
        // errors until they are accessed, so don't blindly create an error
        // here.
        if (qtinst->m_methods.contains(ba))
            return 0;

        // deleted qobject, but can't throw an error from here (no exec)
        // create a fake QtField that will throw upon access
        if (!f) {
            f = new QtField(ba);
            qtinst->m_fields.insert(objName, f);
        }
        return f;
    }
}

}
}

