#pragma once
#include <type_traits>
#include <stdexcept>
#include <exception>
#include "../detail/basic_types.hpp"

namespace lsp::transform
{
        // 通用错误类
    class ConversionError : public std::runtime_error
    {
    public:
        explicit ConversionError(const std::string& message)
            : std::runtime_error("LSP Conversion Error: " + message) {}
    };

    template<typename T>
    struct is_lsp_basic_type: std::false_type {};

    template<> struct is_lsp_basic_type<protocol::boolean> : std::true_type {};
    template<> struct is_lsp_basic_type<protocol::string> : std::true_type {};
    template<> struct is_lsp_basic_type<protocol::decimal> : std::true_type {};
    template<> struct is_lsp_basic_type<std::nullptr_t> : std::true_type {};

    template<typename T>
    struct is_lsp_container_type : std::false_type {};

    template<> struct is_lsp_container_type<protocol::LSPObject> : std::true_type {};
    template<> struct is_lsp_container_type<protocol::LSPArray> : std::true_type {};
    template<> struct is_lsp_container_type<protocol::LSPAny> : std::true_type {};

    // struct类型判断
    template<typename T>
    struct is_user_struct : std::integral_constant<bool,
        !std::is_arithmetic<T>::value &&
        !std::is_same<T, protocol::string>::value &&
        !std::is_same<T, const char*>::value &&
        !std::is_same<T, std::nullptr_t>::value &&
        !is_lsp_basic_type<T>::value &&
        !is_lsp_container_type<T>::value> {};
}
