/*
 * Qt wrapper for libindicate
 *
 * Copyright 2009 Canonical Ltd.
 *
 * Authors:
 * - Aurélien Gâteau <aurelien.gateau@canonical.com>
 *
 * License: LGPL v2.1 or LGPL v3
 */
#ifndef QINDICATELISTENER_H
#define QINDICATELISTENER_H

// Qt
#include <QMetaType>
#include <QObject>

// Local
#include <qindicateinterest.h>

struct _IndicateListener;

namespace QIndicate
{

struct ListenerPrivate;
/**
 * Listener instances talk with Server and Indicator instances over DBus.
 * Since communication is over DBus, pointers to Server and Indicator
 * instances are proxies, not the real instances.
 *
 * Note that there can be only one instance of the Listener per process because
 * it registers a DBus path on the session connection. If you need a listener
 * in multiple independent parts of your code, you can use the
 * defaultInstance() method.
 */
class Listener : public QObject
{
Q_OBJECT
public:
    Listener(QObject* parent = 0);
    ~Listener();

    /**
     * These are dummy structures acting as proxies to the Server and Indicator
     * instances, we only manipulate pointers to them but it's nicer than
     * void* (I wanted to reuse the C typedef, but QSignalSpy disagreed).
     */
    struct Server {};

    struct Indicator {};

    static Listener* defaultInstance();

    /**
     * Ask an indicator for the value of a property. Result will be sent to
     * receiver slot, which should have the following signature:
     *
     *   QIndicate::Listener::Server*,
     *   QIndicate::Listener::Indicator*,
     *   const QString& key,
     *   const QByteArray& value
     *
     *   @deprecated: this method will fail with int or bool properties.
     *   Use getIndicatorPropertyAsVariant instead.
     */
    void getIndicatorProperty(QIndicate::Listener::Server* server, QIndicate::Listener::Indicator* indicator,
                              const QString& property,
                              QObject* receiver, const char* slot);

    /**
     * Ask an indicator for the value of a property. Result will be sent to
     * receiver slot, which should have the following signature:
     *
     *   QIndicate::Listener::Server*,
     *   QIndicate::Listener::Indicator*,
     *   const QString& key,
     *   const QVariant& value
     */
    void getIndicatorPropertyAsVariant(QIndicate::Listener::Server* server, QIndicate::Listener::Indicator* indicator,
                                       const QString& property,
                                       QObject* receiver, const char* slot);

    /**
     * Ask a server for its desktop file. Result will be sent to
     * receiver slot, which should have the following signature:
     *
     *   QIndicate::Listener::Server*,
     *   const QByteArray& value
     */
    void getServerDesktopFile(QIndicate::Listener::Server* server,
                          QObject* receiver, const char* slot);

    /**
     * Ask a server for its type. Result will be sent to receiver slot, which
     * should have the following signature:
     *
     *   QIndicate::Listener::Server*,
     *   const QByteArray& value
     */
    void getServerType(QIndicate::Listener::Server* server,
                       QObject* receiver, const char* slot);

    /**
     * Ask a server for its count. Result will be sent to receiver slot, which
     * should have the following signature:
     *
     *   QIndicate::Listener::Server*,
     *   int value
     */
    void getServerCount(QIndicate::Listener::Server* server,
                        QObject* receiver, const char* slot);

    /**
     * Ask a server for the object path of its associated DBusMenu. Result will
     * be sent to receiver slot, which should have the following signature:
     *
     *   QIndicate::Listener::Server*,
     *   QString value
     */
    void getServerMenuObjectPath(QIndicate::Listener::Server* server,
                                 QObject* receiver, const char* slot);

    /**
     * Ask a server for the dbus name of its associated DBusMenu. Note: unlike
     * the other "getServer..." methods, this one returns the answer immediatly,
     * following libindicate design.
     */
    QString getServerMenuDBusName(QIndicate::Listener::Server* server);

    void display(QIndicate::Listener::Server* server, QIndicate::Listener::Indicator* indicator);

    bool getInterest(QIndicate::Listener::Server*, QIndicate::Interest);

    void setInterest(QIndicate::Listener::Server*, QIndicate::Interest, bool value);

Q_SIGNALS:
    void serverAdded(QIndicate::Listener::Server* server, const QString& type);
    void serverRemoved(QIndicate::Listener::Server* server, const QString& type);
    void serverCountChanged(QIndicate::Listener::Server* server, int count);

    void indicatorAdded(QIndicate::Listener::Server* server, QIndicate::Listener::Indicator* indicator);
    void indicatorModified(QIndicate::Listener::Server* server, QIndicate::Listener::Indicator* indicator, const QString& property);
    void indicatorRemoved(QIndicate::Listener::Server* server, QIndicate::Listener::Indicator* indicator);

private:
    Listener(struct _IndicateListener*);
    void init(struct _IndicateListener*);
    ListenerPrivate* const d;
};

} // namespace

Q_DECLARE_METATYPE(QIndicate::Listener::Server*);
Q_DECLARE_METATYPE(QIndicate::Listener::Indicator*);

#endif /* QINDICATELISTENER_H */
