/*
 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
 *
 *  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 JSC {
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 object and return the same object for the same
// identifier.
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
    JSObject* 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) {
            QtRuntimeMetaMethod* val = new (exec) QtRuntimeMetaMethod(exec, identifier, static_cast<QtInstance*>(inst), index, normal, false);
            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;

        int iter = 0;
        const char* signature = m.signature();
        while (signature[iter] && signature[iter] != '(')
            ++iter;

        if (normal == QByteArray::fromRawData(signature, iter)) {
            QtRuntimeMetaMethod* val = new (exec) QtRuntimeMetaMethod(exec, identifier, static_cast<QtInstance*>(inst), index, normal, false);
            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((const QChar*)ustring.rep()->characters(), 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;
#ifndef QT_NO_PROPERTIES
            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;
                }
            }
#endif
            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;
            }
        }

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

        // 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;

#ifndef QT_NO_PROPERTIES
        // 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);
        }
#endif
        return f;
    }
}

}
}

