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

// Qt
#include <QMetaType>
#include <QImage>
#include <QPainter>
#include <QtTest>

// Local
#include "qindicatedecode.h"

const QString SERVER_TYPE = "message";

QTEST_MAIN(CommunicationTest)

void CommunicationTest::initTestCase()
{
    qRegisterMetaType<QIndicate::Listener::Server*>("QIndicate::Listener::Server*");
    qRegisterMetaType<QIndicate::Listener::Indicator*>("QIndicate::Listener::Indicator*");
    qRegisterMetaType<QIndicate::Interest>("QIndicate::Interest");
    qRegisterMetaType<QIndicate::Indicator*>("QIndicate::Indicator*");
}

void CommunicationTest::init()
{
    mListener = QIndicate::Listener::defaultInstance(); //new QIndicate::Listener;

    mServer = QIndicate::Server::defaultInstance();
    mServer->setType(SERVER_TYPE);

    mIndicator = new QIndicate::Indicator(mServer);

    mListenerServer = 0;
    mListenerIndicator = 0;
}

void CommunicationTest::showIndicatorAndGetProxies()
{
    QSignalSpy addedSpy(mListener, SIGNAL(indicatorAdded(QIndicate::Listener::Server*, QIndicate::Listener::Indicator*)));
    mIndicator->show();
    QTest::qWait(500);

    QCOMPARE(addedSpy.count(), 1);
    QVariantList args = addedSpy.takeFirst();
    mListenerServer = args[0].value<QIndicate::Listener::Server*>();
    mListenerIndicator = args[1].value<QIndicate::Listener::Indicator*>();
    QVERIFY(mListenerServer);
    QVERIFY(mListenerIndicator);
}

void CommunicationTest::cleanup()
{
    delete mServer;
    mServer = 0;
}

void CommunicationTest::testIndicatorModified()
{
    const QString key = "key";
    const QString v1 = "v1";
    const QString v2 = "v2";

    QSignalSpy spy(mListener, SIGNAL(indicatorModified(QIndicate::Listener::Server*, QIndicate::Listener::Indicator*, const QString&)));

    // Should not be notified of changes until mIndicator is shown
    mIndicator->setIndicatorProperty(key, v1);
    QTest::qWait(500);
    QCOMPARE(spy.count(), 0);

    // Now we should get some change
    mIndicator->show();
    QTest::qWait(500);
    mIndicator->setIndicatorProperty(key, v2);
    QTest::qWait(500);

    QCOMPARE(spy.count(), 1);
    QVariantList args = spy.takeFirst();
    QCOMPARE(args[2].toString(), key);
}

static QImage generateTestImage()
{
    QImage image(22, 22, QImage::Format_ARGB32);
    QPainter painter(&image);
    painter.fillRect(image.rect(), Qt::blue);
    painter.fillRect(image.rect().adjusted(4, 4, -4, -4), Qt::black);
    return image;
}

void CommunicationTest::testGetIndicatorProperty()
{
    const QString key1 = "key1";
    const QString v1 = "v1";
    const QString key2 = "key2";
    const QImage v2(generateTestImage());
    const QString key3 = "key3";
    const QDateTime v3 = QDateTime(QDate::currentDate(), QTime(23, 45, 56));

    showIndicatorAndGetProxies();

    mIndicator->setIndicatorProperty(key1, v1);
    mIndicator->setIndicatorProperty(key2, v2);
    mIndicator->setIndicatorProperty(key3, v3);
    QTest::qWait(500);

    PropertyReceiver receiver;

    // key1
    mListener->getIndicatorProperty(mListenerServer, mListenerIndicator, key1,
        &receiver, SLOT(slotIndicatorPropertyReceived(
            QIndicate::Listener::Server*,
            QIndicate::Listener::Indicator*,
            const QString&,
            const QByteArray&)
            )
        );
    QTest::qWait(500);

    QCOMPARE(receiver.server, mListenerServer);
    QCOMPARE(receiver.indicator, mListenerIndicator);
    QCOMPARE(receiver.key, key1);
    QCOMPARE(QIndicate::Decode::stringFromValue(receiver.value.toByteArray()), v1);

    // key2
    mListener->getIndicatorProperty(mListenerServer, mListenerIndicator, key2,
        &receiver, SLOT(slotIndicatorPropertyReceived(
            QIndicate::Listener::Server*,
            QIndicate::Listener::Indicator*,
            const QString&,
            const QByteArray&)
            )
        );
    QTest::qWait(500);

    QCOMPARE(receiver.server, mListenerServer);
    QCOMPARE(receiver.indicator, mListenerIndicator);
    QCOMPARE(receiver.key, key2);
    QCOMPARE(QIndicate::Decode::imageFromValue(receiver.value.toByteArray()), v2);

    // key3
    mListener->getIndicatorProperty(mListenerServer, mListenerIndicator, key3,
        &receiver, SLOT(slotIndicatorPropertyReceived(
            QIndicate::Listener::Server*,
            QIndicate::Listener::Indicator*,
            const QString&,
            const QByteArray&)
            )
        );
    QTest::qWait(500);

    QCOMPARE(receiver.server, mListenerServer);
    QCOMPARE(receiver.indicator, mListenerIndicator);
    QCOMPARE(receiver.key, key3);
    QCOMPARE(QIndicate::Decode::dateTimeFromValue(receiver.value.toByteArray()), v3);
}

void CommunicationTest::testGetServerDesktop()
{
    const QString value = "/path/to/foo.desktop";

    showIndicatorAndGetProxies();

    mServer->setDesktopFile(value);
    QTest::qWait(500);

    PropertyReceiver receiver;

    mListener->getServerDesktopFile(mListenerServer,
                                &receiver,
                                SLOT(slotServerQByteArrayPropertyReceived(
                                     QIndicate::Listener::Server*,
                                     const QByteArray&))
                                );
    QTest::qWait(500);

    QCOMPARE(receiver.server, mListenerServer);
    QCOMPARE(QIndicate::Decode::stringFromValue(receiver.value.toByteArray()), value);
}

void CommunicationTest::testGetServerType()
{
    showIndicatorAndGetProxies();

    PropertyReceiver receiver;

    mListener->getServerType(mListenerServer,
                             &receiver,
                             SLOT(slotServerQByteArrayPropertyReceived(
                                  QIndicate::Listener::Server*,
                                  const QByteArray&))
                             );
    QTest::qWait(500);

    QCOMPARE(receiver.server, mListenerServer);
    QCOMPARE(QIndicate::Decode::stringFromValue(receiver.value.toByteArray()), SERVER_TYPE);
}

void CommunicationTest::testGetServerCount()
{
    QSignalSpy spy(mListener, SIGNAL(serverCountChanged(QIndicate::Listener::Server*, int)));
    QCOMPARE(spy.count(), 0);

    showIndicatorAndGetProxies();
    QCOMPARE(spy.count(), 0);
    PropertyReceiver receiver;

    int count = 12;

    mServer->setCount(count);
    QTest::qWait(500);

    mListener->getServerCount(mListenerServer,
                              &receiver,
                              SLOT(slotServerIntPropertyReceived(
                                   QIndicate::Listener::Server*,
                                   int))
                              );
    QTest::qWait(500);

    QCOMPARE(receiver.server, mListenerServer);
    QCOMPARE(receiver.value.toInt(), count);
    QCOMPARE(spy.count(), 1);
    QVariantList args = spy.takeFirst();
    QCOMPARE(args[0].value<QIndicate::Listener::Server*>(), mListenerServer);
    QCOMPARE(args[1].toInt(), count);
}

void CommunicationTest::testDisplay()
{
    QSignalSpy serverDisplaySpy(mServer, SIGNAL(serverDisplay()));
    QSignalSpy indicatorDisplaySpy(mIndicator, SIGNAL(display(QIndicate::Indicator*)));

    showIndicatorAndGetProxies();

    mListener->display(mListenerServer, 0);
    QTest::qWait(500);
    QCOMPARE(serverDisplaySpy.count(), 1);

    mListener->display(mListenerServer, mListenerIndicator);
    QTest::qWait(500);
    QCOMPARE(indicatorDisplaySpy.count(), 1);
}

void CommunicationTest::testInterest()
{
    const QIndicate::Interest interest = QIndicate::InterestServerDisplay;
    showIndicatorAndGetProxies();

    QSignalSpy interestAddedSpy(mServer, SIGNAL(interestAdded(QIndicate::Interest)));
    QSignalSpy interestRemovedSpy(mServer, SIGNAL(interestRemoved(QIndicate::Interest)));

    QVERIFY(!mListener->getInterest(mListenerServer, interest));

    mListener->setInterest(mListenerServer, interest, true);
    QVERIFY(mListener->getInterest(mListenerServer, interest));
    QTest::qWait(500);
    QCOMPARE(interestAddedSpy.count(), 1);
    QCOMPARE(interestAddedSpy.takeFirst()[0].value<QIndicate::Interest>(), interest);

    mListener->setInterest(mListenerServer, interest, false);
    QVERIFY(!mListener->getInterest(mListenerServer, interest));
    QTest::qWait(500);
    QCOMPARE(interestRemovedSpy.count(), 1);
    QCOMPARE(interestRemovedSpy.takeFirst()[0].value<QIndicate::Interest>(), interest);
}

#include "communicationtest.moc"
