use std::cell::UnsafeCell;
use indexed_valued_enums_derive::{EnumIndexed, EnumValued};

#[test]
fn test() {
    assert_eq!(1, Number::Second.variant_index());
    assert_eq!(Some(Number::Second), Number::from_variant_index(1));
    assert_eq!(None, Number::from_variant_index(231211));
    assert_eq!("Two", Number::Second.name());
    assert_eq!("Two", *Number::Second.name_string());
    assert_eq!("Two", *Number::Second.name_string());
    assert_eq!(2,  Number::Second.num());
    assert_eq!("Second", Number::Second.variant_name());
    assert_eq!(Some(Number::Second), Number::from_name(&"Two"));
    assert_eq!(None, Number::from_name(&"Twowowo"));
    assert_eq!(Some(Number::Second), Number::from_name_string(&"Two"));
    assert_eq!(None, Number::from_name_string(&"Twowowo"));
}



#[derive(Debug, PartialEq)]
#[EnumIndexed]
enum Number {
    First,
    Second,
    Third,
}

#[EnumValued]
pub const fn num(number: &'static Number) -> usize {
    match number {
        Number::First => 1,
        Number::Second => 2,
        Number::Third => 3,
    }
}

#[EnumValued]
pub const fn name(number: &'static Number) -> &'static str {
    match number {
        Number::First => "One",
        Number::Second => "Two",
        Number::Third => "Three",
    }
}

#[EnumValued]
pub fn name_string(number: &'static  Number) -> &'static str {
    number.name()
}

#[derive(Debug)]
#[EnumIndexed(NoFrom)]
enum EnumWithInteriorMutability {
    First,
    Second(UnsafeCell<usize>),
}

#[EnumIndexed(NoFrom, Consts(T: String, O: String))]
enum EnumWithInteriorMutabilityAndTypeParameters<'lf, 'ot, const N: usize, const M: usize, T, O>
where
    T: ToString,
    O: ToString,
{
    First,
    Second(std::cell::UnsafeCell<usize>),
    Third(&'lf &'ot (T, O)),
}

/// Gets a name for every variant
#[EnumValued]
fn custom_name<'lf, 'ot, const N: usize, const M: usize, T, O>(
    v: &'static <EnumWithInteriorMutabilityAndTypeParameters<'lf, 'ot, N, M, T, O> as Fieldless>::Target,
) -> String
where
    T: ToString,
    O: ToString,
{
    match v {
        EnumWithInteriorMutabilityAndTypeParametersVF::First => "first",
        EnumWithInteriorMutabilityAndTypeParametersVF::Second => "second",
        EnumWithInteriorMutabilityAndTypeParametersVF::Third => "third",
    }
        .to_string()
}

#[derive(Debug, PartialEq)]
#[EnumIndexed(FieldlessEnum)]
enum NumberOther {
    First,
    Second,
    Third,
}

