#include <array>
#include "propertywatchimpl.hpp"
#include "propertywatchtest.hpp"

using namespace std::string_literals;
using namespace phosphor::dbus::monitoring;

const std::array<std::string, 4> paths =
{
    "/xyz/openbmc_project/testing/inst1"s,
    "/xyz/openbmc_project/testing/inst2"s,
    "/xyz/openbmc_project/testing/inst3"s,
    "/xyz/openbmc_project/testing/inst4"s,
};

const std::array<std::string, 2> interfaces =
{
    "xyz.openbmc_project.Iface1"s,
    "xyz.openbmc_project.Iface2"s,
};

const std::array<std::string, 2> properties =
{
    "Value1"s,
    "Value2"s,
};

const std::string meta;

std::array<any_ns::any, 8> storage = { };

const PropertyIndex watchIndex =
{
    {
        {
            PropertyIndex::key_type{paths[0], interfaces[0], properties[0]},
            PropertyIndex::mapped_type{meta, meta, storage[0]}
        },
        {
            PropertyIndex::key_type{paths[0], interfaces[1], properties[1]},
            PropertyIndex::mapped_type{meta, meta, storage[1]}
        },
        {
            PropertyIndex::key_type{paths[1], interfaces[0], properties[0]},
            PropertyIndex::mapped_type{meta, meta, storage[2]}
        },
        {
            PropertyIndex::key_type{paths[1], interfaces[1], properties[1]},
            PropertyIndex::mapped_type{meta, meta, storage[3]}
        },
        {
            PropertyIndex::key_type{paths[2], interfaces[0], properties[0]},
            PropertyIndex::mapped_type{meta, meta, storage[4]}
        },
        {
            PropertyIndex::key_type{paths[2], interfaces[1], properties[1]},
            PropertyIndex::mapped_type{meta, meta, storage[5]}
        },
        {
            PropertyIndex::key_type{paths[3], interfaces[0], properties[0]},
            PropertyIndex::mapped_type{meta, meta, storage[6]}
        },
        {
            PropertyIndex::key_type{paths[3], interfaces[1], properties[1]},
            PropertyIndex::mapped_type{meta, meta, storage[7]}
        },
    },
};

template <typename T> struct ExpectedValues {};
template <> struct ExpectedValues<uint8_t>
{
    static auto& get(size_t i)
    {
        static const std::array<uint8_t, 8> values =
        {
            {0, 1, 2, 3, 4, 5, 6, 7},
        };
        return values[i];
    }
};

template <> struct ExpectedValues<uint16_t>
{
    static auto& get(size_t i)
    {
        static const std::array<uint16_t, 8> values =
        {
            {88, 77, 66, 55, 44, 33, 22, 11},
        };
        return values[i];
    }
};

template <> struct ExpectedValues<uint32_t>
{
    static auto& get(size_t i)
    {
        static const std::array<uint32_t, 8> values =
        {
            {0xffffffff, 1, 3, 0, 5, 7, 9, 0xffffffff},
        };
        return values[i];
    }
};

template <> struct ExpectedValues<uint64_t>
{
    static auto& get(size_t i)
    {
        static const std::array<uint64_t, 8> values =
        {
            {0xffffffffffffffff, 3, 7, 12234, 0, 3, 9, 0xffffffff},
        };
        return values[i];
    }
};

template <> struct ExpectedValues<std::string>
{
    static auto& get(size_t i)
    {
        static const std::array<std::string, 8> values =
        {
            {""s, "foo"s, "bar"s, "baz"s, "hello"s, "string", "\x2\x3", "\\"},
        };
        return values[i];
    }
};

template <typename T>
void testStart()
{
    using ::testing::Return;
    using ::testing::_;

    MockDBusInterface dbus;
    MockDBusInterface::instance(dbus);

    const std::vector<std::string> expectedMapperInterfaces;
    PropertyWatchOfType<T, MockDBusInterface> watch(watchIndex);

    auto ndx = static_cast<size_t>(0);
    for (const auto& o : convert(watchIndex))
    {
        const auto& path = o.first.get();
        const auto& interfaces = o.second;
        std::vector<std::string> mapperResponse;
        std::transform(
            interfaces.begin(),
            interfaces.end(),
            std::back_inserter(mapperResponse),
        // *INDENT-OFF*
            [](const auto & item)
            {
                return item.first;
            });
        // *INDENT-ON*
        EXPECT_CALL(
            dbus,
            mapperGetObject(
                MAPPER_BUSNAME,
                MAPPER_PATH,
                MAPPER_INTERFACE,
                "GetObject",
                path,
                expectedMapperInterfaces))
        .WillOnce(Return(GetObject({{"", mapperResponse}})));
        EXPECT_CALL(
            dbus,
            fwdAddMatch(
                sdbusplus::bus::match::rules::member("InterfacesAdded") +
                sdbusplus::bus::match::rules::path(path) +
                sdbusplus::bus::match::rules::interface(
                    "org.freedesktop.DBus.ObjectManager"),
                _));
        for (const auto& i : interfaces)
        {
            const auto& interface = i.first.get();
            const auto& properties = i.second;
            EXPECT_CALL(
                dbus,
                fwdAddMatch(
                    sdbusplus::bus::match::rules::member("PropertiesChanged") +
                    sdbusplus::bus::match::rules::path(path) +
                    sdbusplus::bus::match::rules::argN(0, interface) +
                    sdbusplus::bus::match::rules::interface(
                        "org.freedesktop.DBus.Properties"),
                    _));

            PropertiesChanged<T> serviceResponse;
            for (const auto& p : properties)
            {
                serviceResponse[p] = ExpectedValues<T>::get(ndx);
                ++ndx;
            }
            Expect<T>::getProperties(dbus, path, interface)
            .WillOnce(Return(serviceResponse));
        }
    }

    watch.start();

    ndx = 0;
    for (auto s : storage)
    {
        ASSERT_EQ(s.empty(), false);
        ASSERT_EQ(any_ns::any_cast<T>(s), ExpectedValues<T>::get(ndx));
        ++ndx;
    }

    // Make sure start logic only runs the first time.
    watch.start();
}

TEST(PropertyWatchTest, TestStart)
{
    testStart<uint8_t>();
    testStart<uint16_t>();
    testStart<uint32_t>();
    testStart<uint64_t>();
    testStart<std::string>();
}

MockDBusInterface* MockDBusInterface::ptr = nullptr;
