#pragma once
// #include "./facade.hpp"

namespace lsp::transform
{
    // ==================== JSON 序列化/反序列化 ====================

    template<typename T>
    inline std::optional<T> Deserialize(const std::string& json)
    {
        T obj;
        auto ce = glz::read_json(obj, json);
        if (ce)
            return std::nullopt;
        else
            return obj;
    }

    template<typename T>
    inline std::optional<std::string> Serialize(const T& obj)
    {
        std::string json;
        auto ce = glz::write_json(obj, json);
        if (ce)
            return std::nullopt;
        else
            return json;
    }

    // ==================== 类型检查 ====================

    namespace check
    {
        inline bool IsObject(const protocol::LSPAny& any)
        {
            return any.Is<protocol::LSPObject>();
        }

        inline bool IsArray(const protocol::LSPAny& any)
        {
            return any.Is<protocol::LSPArray>();
        }

        inline bool IsString(const protocol::LSPAny& any)
        {
            return any.Is<protocol::string>();
        }

        inline bool IsNumber(const protocol::LSPAny& any)
        {
            return any.Is<protocol::integer>() ||
                   any.Is<protocol::uinteger>() ||
                   any.Is<protocol::decimal>();
        }

        inline bool IsBool(const protocol::LSPAny& any)
        {
            return any.Is<protocol::boolean>();
        }

        inline bool IsNull(const protocol::LSPAny& any)
        {
            return any.Is<std::nullptr_t>();
        }
    }

    // ==================== 调试工具 ====================

    namespace debug
    {
        inline std::string GetTypeName(const protocol::LSPAny& any)
        {
            if (any.Is<protocol::LSPObject>())
                return "LSPObject";
            if (any.Is<protocol::LSPArray>())
                return "LSPArray";
            if (any.Is<protocol::string>())
                return "string";
            if (any.Is<protocol::integer>())
                return "integer";
            if (any.Is<protocol::uinteger>())
                return "uinteger";
            if (any.Is<protocol::decimal>())
                return "decimal";
            if (any.Is<protocol::boolean>())
                return "boolean";
            if (any.Is<std::nullptr_t>())
                return "null";
            return "unknown";
        }

        inline std::string GetIdString(const std::variant<int, std::string>& id)
        {
            return std::visit([](const auto& value) -> std::string {
                if constexpr (std::is_same_v<std::decay_t<decltype(value)>, int>)
                    return std::to_string(value);
                else
                    return value;
            },
                              id);
        }
    }
}
