#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
