/*
 *   Copyright 2007 Richard J. Moore <rich@kde.org>
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Library General Public License version 2 as
 *   published by the Free Software Foundation
 *
 *   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 Library 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 DATAENGINE_H
#define DATAENGINE_H

#include <QScriptEngine>
#include <QScriptValue>
#include <QScriptValueIterator>
#include <KDebug>

#include <Plasma/DataEngine>
#include <Plasma/Service>
#include <Plasma/ServiceJob>

using namespace Plasma;

#ifndef DECLARATIVE_BINDING
Q_DECLARE_METATYPE(QVariant)
#endif
Q_DECLARE_METATYPE(DataEngine::Dict)
Q_DECLARE_METATYPE(DataEngine::Data)

template <class M>
QScriptValue qScriptValueFromMap(QScriptEngine *eng, const M &map)
{
    //kDebug() << "qScriptValueFromMap called";
    QScriptValue obj = eng->newObject();
    typename M::const_iterator begin = map.constBegin();
    typename M::const_iterator end = map.constEnd();
    typename M::const_iterator it;
    for (it = begin; it != end; ++it) {
        obj.setProperty(it.key(), qScriptValueFromValue(eng, it.value()));
    }

    return obj;
}

template <class M>
QScriptValue qScriptValueFromVariantMap(QScriptEngine *eng, const M &map)
{
    //kDebug() << "qScriptValueFromMap called";
    QScriptValue obj = eng->newObject();
    typename M::const_iterator begin = map.constBegin();
    typename M::const_iterator end = map.constEnd();
    typename M::const_iterator it;
    for (it = begin; it != end; ++it) {
        if (it.value().type() == QVariant::Hash) {
            obj.setProperty(it.key(), qScriptValueFromMap(eng, it.value().toHash()));
        } else if (it.value().type() == QVariant::Map) {
            obj.setProperty(it.key(), qScriptValueFromMap(eng, it.value().toMap()));
        } else {
            obj.setProperty(it.key(), qScriptValueFromValue(eng, it.value()));
        }
    }

    return obj;
}

template <class M>
void qScriptValueToMap(const QScriptValue &value, M &map)
{
    //kDebug() << "qScriptValueToMap called";
    QScriptValueIterator it(value);
    while (it.hasNext()) {
        it.next();
        map[it.name()] = qscriptvalue_cast<typename M::mapped_type>(it.value());
    }
}

template<typename T>
int qScriptRegisterVariantMapMetaType(
    QScriptEngine *engine,
    const QScriptValue &prototype = QScriptValue()
#ifndef qdoc
    , T * /* dummy */ = 0
#endif
)
{
    return qScriptRegisterMetaType<T>(engine, qScriptValueFromVariantMap, qScriptValueToMap, prototype);
}

template<typename T>
int qScriptRegisterMapMetaType(
    QScriptEngine *engine,
    const QScriptValue &prototype = QScriptValue()
#ifndef qdoc
    , T * /* dummy */ = 0
#endif
)
{
    return qScriptRegisterMetaType<T>(engine, qScriptValueFromMap, qScriptValueToMap, prototype);
}

void registerDataEngineMetaTypes(QScriptEngine *engine);

#endif // DATAENGINE_H

