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

namespace lsp::transform
{
    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>
    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;
    }

    template<typename T>
    inline protocol::LSPAny LSPAny(const T& obj)
    {
        return LSPAnyConverter::ToLSPAny(obj);
    }

    template<typename T>
    inline protocol::LSPAny LSPAny(const std::vector<T>& vec)
    {
        return LSPAnyConverter::ToLSPAny(vec);
    }

    template<typename T>
    inline protocol::LSPAny LSPAny(const std::map<protocol::string, T>& map)
    {
        return LSPAnyConverter::ToLSPAny(map);
    }

    template<typename T>
    inline protocol::LSPAny LSPAny(const std::optional<T>& opt)
    {
        return LSPAnyConverter::ToLSPAny(opt);
    }

    template<typename T>
    inline T As(const protocol::LSPAny& any)
    {
        return LSPAnyConverter::FromLSPAny<T>(any);
    }

    template<typename T, typename From>
    inline std::optional<T> As(const std::optional<From>& opt)
    {
        return LSPAnyConverter::As<T>(opt);
    }

    template<typename T, typename... Ts>
    inline T As(const std::variant<Ts...>& var)
    {
        return LSPAnyConverter::As<T>(var);
    }

    template<typename T>
    inline T As(const protocol::LSPObject& obj)
    {
        return LSPAnyConverter::As<T>(obj);
    }

    template<typename T>
    inline T As(const protocol::LSPArray& arr)
    {
        return LSPAnyConverter::As<T>(arr);
    }

    template<typename T>
    inline T Number(const protocol::LSPAny& any)
    {
        return LSPAnyConverter::ToNumber<T>(any);
    }

    template<typename T>
    inline std::vector<T> Vector(const protocol::LSPAny& any)
    {
        return LSPAnyConverter::ToVector<T>(any);
    }

    template<typename T>
    inline std::optional<T> Optional(const protocol::LSPAny& any)
    {
        return LSPAnyConverter::ToOptional<T>(any);
    }

    template<typename T>
    inline protocol::LSPObject LSPObject(const T& obj)
    {
        // 如果已经是 LSPAny，直接获取其中的 LSPObject
        if constexpr (std::is_same_v<T, protocol::LSPAny>)
        {
            return LSPAnyConverter::ToLSPObject(obj);
        }
        else
        {
            // 否则先转换为 LSPAny，再获取 LSPObject
            protocol::LSPAny any = LSPAnyConverter::ToLSPAny(obj);
            return LSPAnyConverter::ToLSPObject(any);
        }
    }

    template<typename T>
    inline protocol::LSPArray LSPArray(const T& container)
    {
        // 如果已经是 LSPAny，直接获取其中的 LSPArray
        if constexpr (std::is_same_v<T, protocol::LSPAny>)
        {
            return LSPAnyConverter::ToLSPArray(container);
        }
        else
        {
            // 否则转换为 LSPAny
            protocol::LSPAny any = LSPAnyConverter::ToLSPAny(container);
            return LSPAnyConverter::ToLSPArray(any);
        }
    }

    inline protocol::string String(const protocol::LSPAny& any)
    {
        return LSPAnyConverter::ToString(any);
    }

    inline protocol::boolean Bool(const protocol::LSPAny& any)
    {
        return LSPAnyConverter::ToBool(any);
    }

}
