#pragma once

#include <nlohmann/json.hpp>
#include <sdbusplus/message/types.hpp>

#include <cmath>
#include <limits>

namespace utils
{

namespace numeric_literals
{
constexpr std::string_view NaN = "NaN";
constexpr std::string_view infinity = "inf";
constexpr std::string_view infinity_negative = "-inf";
} // namespace numeric_literals

inline void from_json(const nlohmann::json& j,
                      sdbusplus::message::object_path& o)
{
    o = j.get<std::string>();
}

inline void from_json(const nlohmann::json& j,
                      std::vector<sdbusplus::message::object_path>& o)
{
    o.clear();
    for (const nlohmann::json& item : j)
    {
        o.emplace_back(item.get<std::string>());
    }
}

inline void to_json(nlohmann::json& j, const double& val)
{
    if (std::isnan(val))
    {
        j = numeric_literals::NaN;
    }
    else if (val == std::numeric_limits<double>::infinity())
    {
        j = numeric_literals::infinity;
    }
    else if (val == -std::numeric_limits<double>::infinity())
    {
        j = numeric_literals::infinity_negative;
    }
    else
    {
        j = val;
    }
}

inline void from_json(const nlohmann::json& j, double& val)
{
    if (j.is_number())
    {
        val = j.get<double>();
    }
    else
    {
        auto str_val = j.get<std::string>();
        if (str_val == numeric_literals::NaN)
        {
            val = std::numeric_limits<double>::quiet_NaN();
        }
        else if (str_val == numeric_literals::infinity)
        {
            val = std::numeric_limits<double>::infinity();
        }
        else if (str_val == numeric_literals::infinity_negative)
        {
            val = -std::numeric_limits<double>::infinity();
        }
        else
        {
            throw std::invalid_argument("Unknown numeric literal");
        }
    }
}

namespace detail
{

template <class T>
struct has_utils_from_json
{
    template <class U>
    static U& ref();

    template <class U>
    static std::true_type check(
        decltype(utils::from_json(ref<const nlohmann::json>(), ref<U>()))*);

    template <class>
    static std::false_type check(...);

    static constexpr bool value =
        decltype(check<std::decay_t<T>>(nullptr))::value;
};

template <class T>
constexpr bool has_utils_from_json_v = has_utils_from_json<T>::value;

template <class T>
struct has_utils_to_json
{
    template <class U>
    static U& ref();

    template <class U>
    static std::true_type
        check(decltype(utils::to_json(ref<nlohmann::json>(), ref<const U>()))*);

    template <class>
    static std::false_type check(...);

    static constexpr bool value =
        decltype(check<std::decay_t<T>>(nullptr))::value;
};

template <class T>
constexpr bool has_utils_to_json_v = has_utils_to_json<T>::value;

bool eq(const auto& a, const auto& b)
{
    if constexpr (std::is_same<std::decay_t<decltype(a)>, double>())
    {
        if (std::isnan(a))
        {
            return std::isnan(b);
        }
    }
    return a == b;
}

} // namespace detail

template <class, class...>
struct LabeledTuple;

template <class... Args, class... Labels>
struct LabeledTuple<std::tuple<Args...>, Labels...>
{
    static_assert(sizeof...(Args) == sizeof...(Labels));

    using tuple_type = std::tuple<Args...>;

    LabeledTuple() = default;
    LabeledTuple(const LabeledTuple&) = default;
    LabeledTuple(LabeledTuple&&) = default;

    explicit LabeledTuple(tuple_type v) : value(std::move(v))
    {}
    LabeledTuple(Args... args) : value(std::move(args)...)
    {}

    LabeledTuple& operator=(const LabeledTuple&) = default;
    LabeledTuple& operator=(LabeledTuple&&) = default;

    nlohmann::json to_json() const
    {
        nlohmann::json j;
        to_json_all(j, std::make_index_sequence<sizeof...(Args)>());
        return j;
    }

    const tuple_type& to_tuple() const
    {
        return value;
    }

    void from_json(const nlohmann::json& j)
    {
        from_json_all(j, std::make_index_sequence<sizeof...(Args)>());
    }

    std::string dump() const
    {
        return to_json().dump();
    }

    template <size_t Idx>
    const auto& at_index() const
    {
        return std::get<Idx>(value);
    }

    template <size_t Idx>
    auto& at_index()
    {
        return std::get<Idx>(value);
    }

    template <class Label>
    const auto& at_label() const
    {
        return find_item<0, Label>(*this);
    }

    template <class Label>
    auto& at_label()
    {
        return find_item<0, Label>(*this);
    }

    bool operator==(const LabeledTuple& other) const
    {
        return std::apply(
            [&](auto&&... x) {
                return std::apply(
                    [&](auto&&... y) {
                        return (true && ... && detail::eq(x, y));
                    },
                    value);
            },
            other.value);
    }

    bool operator<(const LabeledTuple& other) const
    {
        return value < other.value;
    }

  private:
    template <size_t... Idx>
    void to_json_all(nlohmann::json& j, std::index_sequence<Idx...>) const
    {
        (to_json_item<Idx>(j), ...);
    }

    template <size_t Idx>
    void to_json_item(nlohmann::json& j) const
    {
        using Label = std::tuple_element_t<Idx, std::tuple<Labels...>>;
        using T = std::tuple_element_t<Idx, tuple_type>;
        nlohmann::json& item = j[Label::str()];
        if constexpr (detail::has_utils_to_json_v<T>)
        {
            utils::to_json(item, std::get<Idx>(value));
        }
        else
        {
            item = std::get<Idx>(value);
        }
    }

    template <size_t... Idx>
    void from_json_all(const nlohmann::json& j, std::index_sequence<Idx...>)
    {
        (from_json_item<Idx>(j), ...);
    }

    template <size_t Idx>
    void from_json_item(const nlohmann::json& j)
    {
        using Label = std::tuple_element_t<Idx, std::tuple<Labels...>>;
        using T = std::tuple_element_t<Idx, tuple_type>;
        const nlohmann::json& item = j.at(Label::str());
        if constexpr (detail::has_utils_from_json_v<T>)
        {
            T& v = std::get<Idx>(value);
            utils::from_json(item, v);
        }
        else
        {
            std::get<Idx>(value) = item.get<T>();
        }
    }

    template <size_t Idx, class Label, class Self>
    static auto& find_item(Self& self)
    {
        if constexpr (std::is_same_v<Label, std::tuple_element_t<
                                                Idx, std::tuple<Labels...>>>)
        {
            return std::get<Idx>(self.value);
        }
        else
        {
            static_assert(Idx + 1 < sizeof...(Args),
                          "Label not found in LabeledTuple");
            return find_item<Idx + 1, Label>(self);
        }
    }

    tuple_type value;
};

template <class... Args, class... Labels>
inline void to_json(nlohmann::json& json,
                    const LabeledTuple<std::tuple<Args...>, Labels...>& tuple)
{
    json = tuple.to_json();
}

template <class... Args, class... Labels>
inline void from_json(const nlohmann::json& json,
                      LabeledTuple<std::tuple<Args...>, Labels...>& tuple)
{
    tuple.from_json(json);
}

} // namespace utils
