#![allow(dead_code)]

use std::fmt::Debug;
use generate_test_macro::generate_test_macro;

#[derive(Default)]
struct TestTuple(i32);

// Example of using generate_test_macro on a tuple struct with no type parameters.
#[generate_test_macro(generated_macro1)]
impl TestTuple {
    pub fn new(value: i32) -> Self {
        Self(value)
    }

    #[test]
    pub fn static_method() {
        // Static test method to be invoked by the generated macro.
    }

    #[test]
    pub fn instance_method(&self) {
        // Instance test method to be invoked by the generated macro.
    }
}

#[derive(Default)]
struct TestStruct<T> {
    item: T,
}

// Example of using generate_test_macro on a regular struct with type parameters.
#[generate_test_macro(generated_macro2)]
impl<T: Debug> TestStruct<T> {
    pub fn new(item: T) -> Self {
        Self { item }
    }

    #[test]
    pub fn static_method() {
        // Static test method to be invoked by the generated macro.
    }

    #[test]
    pub fn instance_method(&self) {
        // Instance test method to be invoked by the generated macro.
    }
}

// // The output generated by generate_test_macro.
// macro_rules! generated_macro1 {
//     ($mod_name:ident : $type:ty) => {
//         generated_macro1!($mod_name: $type = <$type as Default>::default());
//     };
//     ($mod_name:ident = TestTuple :: <$($tparam:ty),*> $($rest:tt)*) => {
//         generated_macro1!($mod_name : TestTuple <$($tparam),*> = TestTuple :: <$($tparam),*> $($rest)*);
//     };
//     ($mod_name:ident = TestTuple $($rest:tt)*) => {
//         generated_macro1!($mod_name : TestTuple = TestTuple $($rest)*);
//     };
//     ($mod_name:ident : $type:ty = $expr:expr) => {
//         mod $mod_name {
//             use super::*;

//             #[test]
//             fn test_static() {
//                 <$type>::static_method();
//             }

//             #[test]
//             fn test_instance() {
//                 let instance: $type = $expr;
//                 instance.instance_method();
//             }
//         }
//     };
// }

// macro_rules! generated_macro2 {
//     ($mod_name:ident : $type:ty) => {
//         generated_macro2!($mod_name: $type = <$type as Default>::default());
//     };
//     ($mod_name:ident = TestStruct :: <$($tparam:ty),*> $($rest:tt)*) => {
//         generated_macro2!($mod_name : TestStruct <$($tparam),*> = TestStruct :: <$($tparam),*> $($rest)*);
//     };
//     ($mod_name:ident = TestStruct $($rest:tt)*) => {
//         generated_macro2!($mod_name : TestStruct = TestStruct $($rest)*);
//     };
//     ($mod_name:ident : $type:ty = $expr:expr) => {
//         mod $mod_name {
//             use super::*;

//             #[test]
//             fn test_static() {
//                 <$type>::static_method();
//             }

//             #[test]
//             fn test_instance() {
//                 let instance: $type = $expr;
//                 instance.instance_method();
//             }
//         }
//     };
// }

// Examples of how to call the generated macros.

// With just a type.  This works if all test methods are static, or if the type implements Default.
generated_macro1!(tuple_test1: TestTuple);
// With an explicit constructor.
generated_macro1!(tuple_test2 = TestTuple::new(69));
// With tuple struct literal syntax.
generated_macro1!(tuple_test3 = TestTuple(42));

// With just a type.  This works if all test methods are static, or if the type implements Default.
generated_macro2!(struct_test1: TestStruct<u32>);
// With an explicit turbofish constructor.
generated_macro2!(struct_test2 = TestStruct::<u32>::new(69));
// With struct literal syntax.
generated_macro2!(struct_test3 = TestStruct::<u32> { item: 42 });
