#pragma once
#include <type_traits>
#include <stdexcept>
#include <vector>
#include <map>
#include <optional>
#include <variant>
#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) {}
    };

    /// 类型特征：LSP 基本类型判断
    template<typename T>
    inline constexpr bool is_lsp_basic_type_v =
        std::is_same_v<T, protocol::integer> ||
        std::is_same_v<T, protocol::uinteger> ||
        std::is_same_v<T, protocol::decimal> ||
        std::is_same_v<T, protocol::boolean> ||
        std::is_same_v<T, protocol::string> ||
        std::is_same_v<T, std::nullptr_t>;

    /// 类型特征：LSP 容器类型判断
    template<typename T>
    inline constexpr bool is_lsp_container_type_v =
        std::is_same_v<T, protocol::LSPObject> ||
        std::is_same_v<T, protocol::LSPArray> ||
        std::is_same_v<T, protocol::LSPAny>;

    /// 类型特征：检测 vector
    template<typename T>
    struct is_vector : std::false_type
    {
    };

    template<typename T>
    struct is_vector<std::vector<T>> : std::true_type
    {
    };

    template<typename T>
    inline constexpr bool is_vector_v = is_vector<T>::value;

    /// 类型特征：检测 map
    template<typename T>
    struct is_map : std::false_type
    {
    };

    template<typename K, typename V>
    struct is_map<std::map<K, V>> : std::true_type
    {
    };

    template<typename T>
    inline constexpr bool is_map_v = is_map<T>::value;

    /// 类型特征：检测 optional
    template<typename T>
    struct is_optional : std::false_type
    {
    };

    template<typename T>
    struct is_optional<std::optional<T>> : std::true_type
    {
    };

    template<typename T>
    inline constexpr bool is_optional_v = is_optional<T>::value;

    /// 类型特征：检测 variant
    template<typename T>
    struct is_variant : std::false_type
    {
    };

    template<typename... Ts>
    struct is_variant<std::variant<Ts...>> : std::true_type
    {
    };

    template<typename T>
    inline constexpr bool is_variant_v = is_variant<T>::value;

    /// 类型特征：用户自定义 struct 判断
    template<typename T>
    inline constexpr bool is_user_struct_v =
        std::is_class_v<T> &&
        !std::is_pointer_v<T> &&
        !std::is_same_v<T, protocol::string> &&
        !std::is_same_v<T, std::string> &&
        !is_lsp_basic_type_v<T> &&
        !is_lsp_container_type_v<T> &&
        !is_vector_v<T> &&
        !is_map_v<T> &&
        !is_optional_v<T> &&
        !is_variant_v<T>;
}
