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

namespace lsp::transform
{

    // ===== 全局便利函数 =====
    template<typename T>
    std::optional<T> Deserialize(const std::string& json);

    template<typename T>
    std::optional<std::string> Serialize(const T& obj);

    // 基本类型
    template<typename T>
    protocol::LSPAny LSPAny(const T& obj);

    // // struct 类型
    // template<typename T>
    // typename std::enable_if<is_user_struct<T>::value, protocol::LSPAny>::type LSPAny(const T& value);

    // 容器类型
    template<typename T>
    protocol::LSPAny LSPAny(const std::vector<T>& vec);

    template<typename T>
    protocol::LSPAny LSPAny(const std::map<protocol::string, T>& map);

    template<typename T>
    protocol::LSPAny LSPAny(const std::optional<T>& opt);

    template<typename T>
    T As(const protocol::LSPAny& any);

    template<typename T, typename From>
    std::optional<T> As(const std::optional<From>& opt);

    template<typename T, typename... Ts>
    T As(const std::variant<Ts...>& var);

    template<typename T>
    T As(const protocol::LSPObject& obj);

    template<typename T>
    T As(const protocol::LSPArray& arr);

    template<typename T>
    T Number(const protocol::LSPAny& any);

    template<typename T>
    std::vector<T> Vector(const protocol::LSPAny& any);

    template<typename T>
    std::optional<T> Optional(const protocol::LSPAny& any);

    template<typename T>
    protocol::LSPObject LSPObject(const T& obj);

    template<typename T>
    protocol::LSPArray LSPArray(const T& vec);

    protocol::string String(const protocol::LSPAny& any);
    protocol::boolean Bool(const protocol::LSPAny& any);

    // === 外观接口：类型检查 ===
    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::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::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);
        }
    }
}

#include "./facade.inl"
