#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<std::tuple<any_ns::any, 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(std::get<0>(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;
