/*
 * Copyright 2013 Canonical Ltd.
 *
 * This program is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 3, 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 warranties of
 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
 * PURPOSE.  See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program.  If not, see .
 *
 * Authors:
 *   Charles Kerr 
 */
#include "actions-mock.h"
#include "state-mock.h"
#include "glib-fixture.h"
#include "dbus-alarm-properties.h"
#include 
#include 
#include 
#include 
#include 
using namespace unity::indicator::datetime;
class ExporterFixture: public GlibFixture
{
private:
    typedef GlibFixture super;
protected:
    GTestDBus* bus = nullptr;
    void SetUp() override
    {
        super::SetUp();
        // bring up the test bus
        bus = g_test_dbus_new(G_TEST_DBUS_NONE);
        g_test_dbus_up(bus);
        const auto address = g_test_dbus_get_bus_address(bus);
        g_setenv("DBUS_SYSTEM_BUS_ADDRESS", address, true);
        g_setenv("DBUS_SESSION_BUS_ADDRESS", address, true);
    }
    void TearDown() override
    {
        GError * error = nullptr;
        GDBusConnection* connection = g_bus_get_sync(G_BUS_TYPE_SESSION, nullptr, &error);
        if(!g_dbus_connection_is_closed(connection))
            g_dbus_connection_close_sync(connection, nullptr, &error);
        g_assert_no_error(error);
        g_clear_object(&connection);
        g_test_dbus_down(bus);
        g_clear_object(&bus);
        super::TearDown();
    }
};
TEST_F(ExporterFixture, HelloWorld)
{
    // confirms that the Test DBus SetUp() and TearDown() works
}
TEST_F(ExporterFixture, Publish)
{
    auto state = std::make_shared();
    auto actions = std::make_shared(state);
    auto settings = std::make_shared();
    std::vector> menus;
    MenuFactory menu_factory (actions, state);
    for(int i=0; i names;
    for(int i=0; names_strv && names_strv[i]; i++)
      names.insert(names_strv[i]);
    // confirm the actions that we expect
    EXPECT_EQ(1, names.count("desktop.open-alarm-app"));
    EXPECT_EQ(1, names.count("desktop.open-appointment"));
    EXPECT_EQ(1, names.count("desktop.open-calendar-app"));
    EXPECT_EQ(1, names.count("desktop.open-settings-app"));
    EXPECT_EQ(1, names.count("phone.open-alarm-app"));
    EXPECT_EQ(1, names.count("phone.open-appointment"));
    EXPECT_EQ(1, names.count("phone.open-calendar-app"));
    EXPECT_EQ(1, names.count("phone.open-settings-app"));
    EXPECT_EQ(1, names.count("calendar"));
    EXPECT_EQ(1, names.count("desktop_greeter-header"));
    EXPECT_EQ(1, names.count("desktop-header"));
    EXPECT_EQ(1, names.count("phone_greeter-header"));
    EXPECT_EQ(1, names.count("phone-header"));
    EXPECT_EQ(1, names.count("set-location"));
    // try closing the connection prematurely
    // to test Exporter's name-lost signal
    bool name_lost = false;
    exporter.name_lost().connect([this,&name_lost](){
        name_lost = true;
        g_main_loop_quit(loop);
    });
    g_dbus_connection_close_sync(connection, nullptr, nullptr);
    g_main_loop_run(loop);
    EXPECT_TRUE(name_lost);
    // cleanup
    g_strfreev(names_strv);
    g_clear_object(&exported);
    g_clear_object(&connection);
}
TEST_F(ExporterFixture, AlarmProperties)
{
    /***
    **** Set up the exporter
    ***/
    std::shared_ptr state(new MockState);
    std::shared_ptr actions(new MockActions(state));
    std::shared_ptr settings(new Settings);
    std::vector> menus;
    MenuFactory menu_factory (actions, state);
    for(int i=0; i(gproxy) = datetime_alarm_properties_proxy_new_for_bus_finish(res, &error);
        EXPECT_TRUE(error == nullptr);
    };
    DatetimeAlarmProperties* proxy = nullptr;
    datetime_alarm_properties_proxy_new_for_bus(G_BUS_TYPE_SESSION,
                                                G_DBUS_PROXY_FLAGS_NONE,
                                                BUS_DATETIME_NAME,
                                                BUS_DATETIME_PATH"/AlarmProperties",
                                                nullptr,
                                                on_proxy_ready,
                                                &proxy);
    wait_msec(100);
    ASSERT_TRUE(proxy != nullptr);
    /***
    **** Try changing the Settings -- do the DBus properties change to match it?
    ***/
    auto expected_volume = 1;
    int expected_duration = 4;
    int expected_snooze_duration = 5;
    const char * expected_sound = "/tmp/foo.wav";
    const char * expected_haptic = "pulse";
    settings->alarm_volume.set(expected_volume);
    settings->alarm_duration.set(expected_duration);
    settings->snooze_duration.set(expected_snooze_duration);
    settings->alarm_sound.set(expected_sound);
    settings->alarm_haptic.set(expected_haptic);
    wait_msec();
    static constexpr const char* const SOUND_PROP {"default-sound"};
    static constexpr const char* const VOLUME_PROP {"default-volume"};
    static constexpr const char* const DURATION_PROP {"duration"};
    static constexpr const char* const HAPTIC_PROP {"haptic-feedback"};
    static constexpr const char* const SNOOZE_PROP {"snooze-duration"};
    char* sound = nullptr;
    char* haptic = nullptr;
    int volume = -1;
    int duration = -1;
    int snooze = -1;
    g_object_get(proxy, SOUND_PROP, &sound,
                        HAPTIC_PROP, &haptic,
                        VOLUME_PROP, &volume,
                        DURATION_PROP, &duration,
                        SNOOZE_PROP, &snooze,
                        nullptr);
    EXPECT_STREQ(expected_sound, sound);
    EXPECT_STREQ(expected_haptic, haptic);
    EXPECT_EQ(expected_volume, volume);
    EXPECT_EQ(expected_duration, duration);
    EXPECT_EQ(expected_snooze_duration, snooze);
    g_clear_pointer (&sound, g_free);
    g_clear_pointer (&haptic, g_free);
    /***
    **** Try changing the DBus properties -- do the Settings change to match it?
    ***/
    expected_volume = 100;
    expected_duration = 30;
    expected_sound = "/tmp/bar.wav";
    expected_haptic = "none";
    expected_snooze_duration = 5;
    g_object_set(proxy, SOUND_PROP, expected_sound,
                        HAPTIC_PROP, expected_haptic,
                        VOLUME_PROP, expected_volume,
                        DURATION_PROP, expected_duration,
                        SNOOZE_PROP, expected_snooze_duration,
                        nullptr);
    wait_msec();
    EXPECT_STREQ(expected_sound, settings->alarm_sound.get().c_str());
    EXPECT_STREQ(expected_haptic, settings->alarm_haptic.get().c_str());
    EXPECT_EQ(expected_volume, settings->alarm_volume.get());
    EXPECT_EQ(expected_duration, settings->alarm_duration.get());
    EXPECT_EQ(expected_snooze_duration, settings->snooze_duration.get());
    // cleanup
    g_clear_object(&proxy);
}