#include "dbus_environment.hpp"
#include "mocks/sensor_listener_mock.hpp"
#include "printers.hpp"
#include "sensor.hpp"
#include "sensor_cache.hpp"
#include "stubs/dbus_sensor_object.hpp"
#include "utils/sensor_id_eq.hpp"

#include <sdbusplus/asio/property.hpp>

#include <thread>

#include <gmock/gmock.h>

using namespace testing;
using namespace std::chrono_literals;

class TestSensor : public Test
{
  public:
    void SetUp() override
    {
        sensorObject.setValue(42.7);
    }

    void TearDown() override
    {
        DbusEnvironment::synchronizeIoc();
    }

    void
        registerForUpdates(std::shared_ptr<interfaces::SensorListener> listener)
    {
        DbusEnvironment::synchronizedPost(
            [this, listener] { sut->registerForUpdates(listener); });
    }

    std::chrono::milliseconds notifiesInGivenIntervalAfterSchedule(
        std::chrono::milliseconds interval);

    stubs::DbusSensorObject sensorObject{DbusEnvironment::getIoc(),
                                         DbusEnvironment::getBus(),
                                         DbusEnvironment::getObjServer()};

    SensorCache sensorCache;
    uint64_t timestamp = std::time(0);
    std::shared_ptr<Sensor> sut = sensorCache.makeSensor<Sensor>(
        DbusEnvironment::serviceName(), sensorObject.path(),
        DbusEnvironment::getIoc(), DbusEnvironment::getBus());
    std::shared_ptr<SensorListenerMock> listenerMock =
        std::make_shared<StrictMock<SensorListenerMock>>();
    std::shared_ptr<SensorListenerMock> listenerMock2 =
        std::make_shared<StrictMock<SensorListenerMock>>();
};

TEST_F(TestSensor, createsCorretlyViaSensorCache)
{
    ASSERT_THAT(sut->id(),
                sensorIdEq(Sensor::Id("Sensor", DbusEnvironment::serviceName(),
                                      sensorObject.path())));
}

TEST_F(TestSensor, notifiesWithValueAfterRegister)
{
    EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7))
        .WillOnce(InvokeWithoutArgs(DbusEnvironment::setPromise("async_read")));

    registerForUpdates(listenerMock);

    ASSERT_TRUE(DbusEnvironment::waitForFuture("async_read"));
}

TEST_F(TestSensor, notifiesOnceWithValueAfterRegister)
{
    EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7))
        .WillOnce(InvokeWithoutArgs(DbusEnvironment::setPromise("async_read")));
    EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7))
        .WillOnce(
            InvokeWithoutArgs(DbusEnvironment::setPromise("async_read2")));

    DbusEnvironment::synchronizedPost([this] {
        sut->registerForUpdates(listenerMock);
        sut->registerForUpdates(listenerMock2);
    });

    ASSERT_TRUE(DbusEnvironment::waitForFuture("async_read"));
    ASSERT_TRUE(DbusEnvironment::waitForFuture("async_read2"));
}

class TestSensorNotification : public TestSensor
{
  public:
    void SetUp() override
    {
        EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 0.))
            .WillOnce(
                InvokeWithoutArgs(DbusEnvironment::setPromise("async_read")));

        registerForUpdates(listenerMock);

        ASSERT_TRUE(DbusEnvironment::waitForFuture("async_read"));
    }

    std::shared_ptr<SensorListenerMock> listenerMock2 =
        std::make_shared<StrictMock<SensorListenerMock>>();
};

TEST_F(TestSensorNotification, notifiesListenerWithValueWhenChangeOccurs)
{
    EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7))
        .WillOnce(InvokeWithoutArgs(DbusEnvironment::setPromise("notify")));

    sensorObject.setValue(42.7);

    ASSERT_TRUE(DbusEnvironment::waitForFuture("notify"));
}

TEST_F(TestSensorNotification, notifiesListenerWithValueWhenNoChangeOccurs)
{
    Sequence seq;

    EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7))
        .InSequence(seq);
    EXPECT_CALL(*listenerMock, sensorUpdated(Ref(*sut), Ge(timestamp)))
        .InSequence(seq)
        .WillOnce(InvokeWithoutArgs(DbusEnvironment::setPromise("notify")));

    sensorObject.setValue(42.7);
    sensorObject.setValue(42.7);

    ASSERT_TRUE(DbusEnvironment::waitForFuture("notify"));
}

TEST_F(TestSensorNotification, doesntNotifyExpiredListener)
{
    Sequence seq;
    EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 0.))
        .InSequence(seq);
    EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 42.7))
        .InSequence(seq)
        .WillOnce(InvokeWithoutArgs(DbusEnvironment::setPromise("notify")));

    registerForUpdates(listenerMock2);
    listenerMock = nullptr;

    sensorObject.setValue(42.7);

    ASSERT_TRUE(DbusEnvironment::waitForFuture("notify"));
}

TEST_F(TestSensorNotification, notifiesWithValueDuringRegister)
{
    EXPECT_CALL(*listenerMock2, sensorUpdated(Ref(*sut), Ge(timestamp), 0.));

    registerForUpdates(listenerMock2);
}
