use std::sync::LazyLock;

use hashbrown::HashSet;

// MSLS - Metal Shading Language Specification:
// https://developer.apple.com/metal/Metal-Shading-Language-Specification.pdf
//
// C++ - Standard for Programming Language C++ (N4431)
// https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4431.pdf
pub const RESERVED: &[&str] = &[
    // Undocumented
    "assert", // found in https://github.com/gfx-rs/wgpu/issues/5347
    // Standard for Programming Language C++ (N4431): 2.5 Alternative tokens
    "and",
    "bitor",
    "or",
    "xor",
    "compl",
    "bitand",
    "and_eq",
    "or_eq",
    "xor_eq",
    "not",
    "not_eq",
    // Standard for Programming Language C++ (N4431): 2.11 Keywords
    "alignas",
    "alignof",
    "asm",
    "auto",
    "bool",
    "break",
    "case",
    "catch",
    "char",
    "char16_t",
    "char32_t",
    "class",
    "const",
    "constexpr",
    "const_cast",
    "continue",
    "decltype",
    "default",
    "delete",
    "do",
    "double",
    "dynamic_cast",
    "else",
    "enum",
    "explicit",
    "export",
    "extern",
    "false",
    "float",
    "for",
    "friend",
    "goto",
    "if",
    "inline",
    "int",
    "long",
    "mutable",
    "namespace",
    "new",
    "noexcept",
    "nullptr",
    "operator",
    "private",
    "protected",
    "public",
    "register",
    "reinterpret_cast",
    "return",
    "short",
    "signed",
    "sizeof",
    "static",
    "static_assert",
    "static_cast",
    "struct",
    "switch",
    "template",
    "this",
    "thread_local",
    "throw",
    "true",
    "try",
    "typedef",
    "typeid",
    "typename",
    "union",
    "unsigned",
    "using",
    "virtual",
    "void",
    "volatile",
    "wchar_t",
    "while",
    // Metal Shading Language Specification: 1.4.4 Restrictions
    "main",
    // Metal Shading Language Specification: 2.1 Scalar Data Types
    "int8_t",
    "uchar",
    "uint8_t",
    "int16_t",
    "ushort",
    "uint16_t",
    "int32_t",
    "uint",
    "uint32_t",
    "int64_t",
    "uint64_t",
    "half",
    "bfloat",
    "size_t",
    "ptrdiff_t",
    // Metal Shading Language Specification: 2.2 Vector Data Types
    "bool2",
    "bool3",
    "bool4",
    "char2",
    "char3",
    "char4",
    "short2",
    "short3",
    "short4",
    "int2",
    "int3",
    "int4",
    "long2",
    "long3",
    "long4",
    "uchar2",
    "uchar3",
    "uchar4",
    "ushort2",
    "ushort3",
    "ushort4",
    "uint2",
    "uint3",
    "uint4",
    "ulong2",
    "ulong3",
    "ulong4",
    "half2",
    "half3",
    "half4",
    "bfloat2",
    "bfloat3",
    "bfloat4",
    "float2",
    "float3",
    "float4",
    "vec",
    // Metal Shading Language Specification: 2.2.3 Packed Vector Types
    "packed_bool2",
    "packed_bool3",
    "packed_bool4",
    "packed_char2",
    "packed_char3",
    "packed_char4",
    "packed_short2",
    "packed_short3",
    "packed_short4",
    "packed_int2",
    "packed_int3",
    "packed_int4",
    "packed_uchar2",
    "packed_uchar3",
    "packed_uchar4",
    "packed_ushort2",
    "packed_ushort3",
    "packed_ushort4",
    "packed_uint2",
    "packed_uint3",
    "packed_uint4",
    "packed_half2",
    "packed_half3",
    "packed_half4",
    "packed_bfloat2",
    "packed_bfloat3",
    "packed_bfloat4",
    "packed_float2",
    "packed_float3",
    "packed_float4",
    "packed_long2",
    "packed_long3",
    "packed_long4",
    "packed_vec",
    // Metal Shading Language Specification: 2.3 Matrix Data Types
    "half2x2",
    "half2x3",
    "half2x4",
    "half3x2",
    "half3x3",
    "half3x4",
    "half4x2",
    "half4x3",
    "half4x4",
    "float2x2",
    "float2x3",
    "float2x4",
    "float3x2",
    "float3x3",
    "float3x4",
    "float4x2",
    "float4x3",
    "float4x4",
    "matrix",
    // Metal Shading Language Specification: 2.6 Atomic Data Types
    "atomic",
    "atomic_int",
    "atomic_uint",
    "atomic_bool",
    "atomic_ulong",
    "atomic_float",
    // Metal Shading Language Specification: 2.20 Type Conversions and Re-interpreting Data
    "as_type",
    // Metal Shading Language Specification: 4 Address Spaces
    "device",
    "constant",
    "thread",
    "threadgroup",
    "threadgroup_imageblock",
    "ray_data",
    "object_data",
    // Metal Shading Language Specification: 5.1 Functions
    "vertex",
    "fragment",
    "kernel",
    // Metal Shading Language Specification: 6.1 Namespace and Header Files
    "metal",
    // C99 / C++ extension:
    "restrict",
    // Metal reserved types in <metal_types>:
    "llong",
    "ullong",
    "quad",
    "complex",
    "imaginary",
    // Constants in <metal_types>:
    "CHAR_BIT",
    "SCHAR_MAX",
    "SCHAR_MIN",
    "UCHAR_MAX",
    "CHAR_MAX",
    "CHAR_MIN",
    "USHRT_MAX",
    "SHRT_MAX",
    "SHRT_MIN",
    "UINT_MAX",
    "INT_MAX",
    "INT_MIN",
    "ULONG_MAX",
    "LONG_MAX",
    "LONG_MIN",
    "ULLONG_MAX",
    "LLONG_MAX",
    "LLONG_MIN",
    "FLT_DIG",
    "FLT_MANT_DIG",
    "FLT_MAX_10_EXP",
    "FLT_MAX_EXP",
    "FLT_MIN_10_EXP",
    "FLT_MIN_EXP",
    "FLT_RADIX",
    "FLT_MAX",
    "FLT_MIN",
    "FLT_EPSILON",
    "FLT_DECIMAL_DIG",
    "FP_ILOGB0",
    "FP_ILOGB0",
    "FP_ILOGBNAN",
    "FP_ILOGBNAN",
    "MAXFLOAT",
    "HUGE_VALF",
    "INFINITY",
    "NAN",
    "M_E_F",
    "M_LOG2E_F",
    "M_LOG10E_F",
    "M_LN2_F",
    "M_LN10_F",
    "M_PI_F",
    "M_PI_2_F",
    "M_PI_4_F",
    "M_1_PI_F",
    "M_2_PI_F",
    "M_2_SQRTPI_F",
    "M_SQRT2_F",
    "M_SQRT1_2_F",
    "HALF_DIG",
    "HALF_MANT_DIG",
    "HALF_MAX_10_EXP",
    "HALF_MAX_EXP",
    "HALF_MIN_10_EXP",
    "HALF_MIN_EXP",
    "HALF_RADIX",
    "HALF_MAX",
    "HALF_MIN",
    "HALF_EPSILON",
    "HALF_DECIMAL_DIG",
    "MAXHALF",
    "HUGE_VALH",
    "M_E_H",
    "M_LOG2E_H",
    "M_LOG10E_H",
    "M_LN2_H",
    "M_LN10_H",
    "M_PI_H",
    "M_PI_2_H",
    "M_PI_4_H",
    "M_1_PI_H",
    "M_2_PI_H",
    "M_2_SQRTPI_H",
    "M_SQRT2_H",
    "M_SQRT1_2_H",
    "DBL_DIG",
    "DBL_MANT_DIG",
    "DBL_MAX_10_EXP",
    "DBL_MAX_EXP",
    "DBL_MIN_10_EXP",
    "DBL_MIN_EXP",
    "DBL_RADIX",
    "DBL_MAX",
    "DBL_MIN",
    "DBL_EPSILON",
    "DBL_DECIMAL_DIG",
    "MAXDOUBLE",
    "HUGE_VAL",
    "M_E",
    "M_LOG2E",
    "M_LOG10E",
    "M_LN2",
    "M_LN10",
    "M_PI",
    "M_PI_2",
    "M_PI_4",
    "M_1_PI",
    "M_2_PI",
    "M_2_SQRTPI",
    "M_SQRT2",
    "M_SQRT1_2",
    // Naga utilities
    "DefaultConstructible",
    super::writer::FREXP_FUNCTION,
    super::writer::MODF_FUNCTION,
    super::writer::ABS_FUNCTION,
    super::writer::DIV_FUNCTION,
    super::writer::MOD_FUNCTION,
    super::writer::NEG_FUNCTION,
    super::writer::F2I32_FUNCTION,
    super::writer::F2U32_FUNCTION,
    super::writer::F2I64_FUNCTION,
    super::writer::F2U64_FUNCTION,
    super::writer::ARGUMENT_BUFFER_WRAPPER_STRUCT,
];

/// The above set of reserved keywords, turned into a cached HashSet. This saves
/// significant time during [`Namer::reset`](crate::proc::Namer::reset).
///
/// See <https://github.com/gfx-rs/wgpu/pull/7338> for benchmarks.
pub static RESERVED_SET: LazyLock<HashSet<&'static str>> = LazyLock::new(|| {
    let mut set = HashSet::default();
    set.reserve(RESERVED.len());
    for &word in RESERVED {
        set.insert(word);
    }
    set
});
