"""
This is a helper script to generate the multi-field variants of the
__c_enum_impl! macro.

USAGE: python3 scripts/enum-impl.py > src/decl_variants.rs
"""


def emit_multi_variant(count):
    print(
        f"""\
    // Match {count} fields
    (
        impl($name:ident, $inner:ty, $default:expr)
"""
    )

    for i in range(0, count):
        index = i + 1

        print(
            f"""\
        $( #[$attr{index}:meta] )*
        $field{index}:ident $( = $value{index}:expr )? ,
"""
        )

    print(
        """\
        $(
            $( #[$rattr:meta] )*
            $frest:ident $( = $frest_val:expr )?
        ),* $(,)?
    ) => {\
"""
    )

    for i in range(0, count):
        index = i + 1

        if index == 1:
            prev = "$default"
        else:
            prev = f"Self::$field{index - 1}.0 + 1"

        print(
            f"""\
        $( #[$attr{index}] )*
        #[allow(non_upper_case_globals)]
        pub const $field{index}: Self = Self($crate::__c_enum_impl!(
            impl(first_expr) $( $value{index}, )? {prev}));
"""
        )

    print(
        f"""\
        $crate::__c_enum_decl_variants!(
            impl($name, $inner, Self::$field{count}.0 + 1)
            $( $( #[$rattr] )* $frest $( = $frest_val )?, )*
        );
    }};
"""
    )


print(
    """\
/// Helper macro for defining the fields of a c_enum!
///
/// Large enums can easily hit the recursion limit imposed by rustc on macros.
/// This macro defines a bunch of variants which consume a bunch of fields at
/// once with the goal being to reduce the recursion limit to something
/// managable even for large enum definitions.
///
/// This code is generated by scripts/enum-impl.py. Don't edit it manually.
/// Edit the script and regenerate it instead.
#[doc(hidden)]
#[macro_export]
macro_rules! __c_enum_decl_variants {
    (impl($name:ident, $inner:ty, $default:expr)) => {};
"""
)

# ~10k variants ought to be enough for now. Anyone going over that can probably
# afford to bump up rustc's recursion limit.
emit_multi_variant(128)
emit_multi_variant(32)
emit_multi_variant(8)

print(
    """\
    // Base case
    (
        impl($name:ident, $inner:ty, $default:expr)
        $( #[$fattr:meta] )*
        $field:ident $( = $fvalue:expr )?
        $( ,
            $( #[$rattr:meta] )*
            $frest:ident $( = $frest_val:expr )?
        )*
        $(,)?
    ) => {
        $( #[$fattr] )*
        #[allow(non_upper_case_globals)]
        pub const $field: Self = Self($crate::__c_enum_impl!(
            impl(first_expr) $( $fvalue, )? $default));

        $crate::__c_enum_decl_variants!(
            impl($name, $inner, Self::$field.0 + 1)
            $( $( #[$rattr] )* $frest $( = $frest_val )?, )*
        );
    }
}\
"""
)
