#include <tests/lib/test.h>

#include <TelepathyQt/Channel>
#include <TelepathyQt/Types>
#include <TelepathyQt/types-internal.h>

using namespace Tp;

/* We need a interface returning a QVariantMap property where we will insert the various
 * combinations we are testing, so let's use Channel.Tube for that as we already have the
 * autogenerated interface for it */
class TubeAdaptor : public QDBusAbstractAdaptor
{
    Q_OBJECT
    Q_CLASSINFO("D-Bus Interface", "org.freedesktop.Telepathy.Channel.Interface.Tube")
    Q_CLASSINFO("D-Bus Introspection", ""
"  <interface name=\"org.freedesktop.Telepathy.Channel.Interface.Tube\" >\n"
"    <property name=\"Parameters\" type=\"a{sv}\" access=\"read\" />\n"
"  </interface>\n"
        "")

    Q_PROPERTY(QVariantMap Parameters READ Parameters)

public:
    TubeAdaptor(QObject *parent) : QDBusAbstractAdaptor(parent) {}
    ~TubeAdaptor() {}

public: // Properties
    inline QVariantMap Parameters() const
    {
        QVariantMap ret;

        SUSocketAddress su;
        su.address = QLatin1String("1.1.1.1");
        su.port = 1111;
        SocketAddressIPv4 saIPv4;
        saIPv4.address = QLatin1String("2.2.2.2");
        saIPv4.port = 2222;
        SocketAddressIPv6 saIPv6;
        saIPv6.address = QLatin1String("3.3.3.3");
        saIPv6.port = 3333;
        ret.insert(QLatin1String("SU"), qVariantFromValue(su));
        ret.insert(QLatin1String("saIPv4"), qVariantFromValue(saIPv4));
        ret.insert(QLatin1String("saIPv6"), qVariantFromValue(saIPv6));

        return ret;
    }
};

class TestTypes : public Test
{
    Q_OBJECT

public:
    TestTypes(QObject *parent = 0)
        : Test(parent)
    { }

protected Q_SLOTS:

private Q_SLOTS:
    void initTestCase();
    void init();

    void testParameters();

    void cleanup();
    void cleanupTestCase();

private:
    QVariantMap mParameters;
};

void TestTypes::initTestCase()
{
    initTestCaseImpl();

    QDBusConnection bus = QDBusConnection::sessionBus();

    // setup adaptor
    QString tubeBusName = QLatin1String("org.freedesktop.Telepathy.Test.Types");
    QString tubePath = QLatin1String("/org/freedesktop/Telepathy/Test/Types");

    QObject *adaptorObject = new QObject(this);
    (void) new TubeAdaptor(adaptorObject);
    QVERIFY(bus.registerService(tubeBusName));
    QVERIFY(bus.registerObject(tubePath, adaptorObject));

    Client::ChannelInterfaceTubeInterface *tubeIface = new Client::ChannelInterfaceTubeInterface(
            bus, tubeBusName, tubePath, this);
    QVERIFY(waitForProperty(tubeIface->requestPropertyParameters(), &mParameters));
}

void TestTypes::init()
{
    initImpl();
}

void TestTypes::testParameters()
{
    SUSocketAddress su;
    SocketAddressIPv4 saIPv4;
    SocketAddressIPv6 saIPv6;

    // SUSocketAddress should properly convert to SUSocketAddress itself and
    // SocketAddressIPv4/IPv6
    su = qdbus_cast<SUSocketAddress>(mParameters.value(QLatin1String("SU")));
    QCOMPARE(su.address, QLatin1String("1.1.1.1"));
    QCOMPARE(su.port, static_cast<uint>(1111));

    saIPv4 = qdbus_cast<SocketAddressIPv4>(mParameters.value(QLatin1String("SU")));
    QCOMPARE(saIPv4.address, QLatin1String("1.1.1.1"));
    QCOMPARE(saIPv4.port, static_cast<ushort>(1111));

    saIPv6 = qdbus_cast<SocketAddressIPv6>(mParameters.value(QLatin1String("SU")));
    QCOMPARE(saIPv6.address, QLatin1String("1.1.1.1"));
    QCOMPARE(saIPv6.port, static_cast<ushort>(1111));

    // SocketAddressIPv4->SocketAddressIPv4
    saIPv4 = qdbus_cast<SocketAddressIPv4>(mParameters.value(QLatin1String("saIPv4")));
    QCOMPARE(saIPv4.address, QLatin1String("2.2.2.2"));
    QCOMPARE(saIPv4.port, static_cast<ushort>(2222));

    // SocketAddressIPv6->SocketAddressIPv6
    saIPv6 = qdbus_cast<SocketAddressIPv6>(mParameters.value(QLatin1String("saIPv6")));
    QCOMPARE(saIPv6.address, QLatin1String("3.3.3.3"));
    QCOMPARE(saIPv6.port, static_cast<ushort>(3333));
}

void TestTypes::cleanup()
{
    cleanupImpl();
}

void TestTypes::cleanupTestCase()
{
    cleanupTestCaseImpl();
}

QTEST_MAIN(TestTypes)
#include "_gen/types.cpp.moc.hpp"
