use std::cell::OnceCell;
use std::sync::Mutex;
use indexed_valued_enums_derive::{EnumIndexed, EnumValued};

#[test]
fn test() {
    let a = TypedEnum::<5, true, u8, u8>::Middle(5);
    assert_eq!(2, a.variant_index());
    assert_ne!(0, a.variant_index());
    TypedEnum::<5, true, u8, u8>::VARIANTS_NAMES
        .iter()
        .for_each(|_n| {});
    let v = TypedEnum::<0, false, u8, u8>::SoftTwo(&(&5));
    assert_eq!(1, v.variant_index());
    assert_eq!(Some(TypedEnum::<0,false,u8,u8>::SoftTwo(&&0)), TypedEnum::<0,false,u8,u8>::from_variant_index(v.variant_index()));
    assert_eq!(&2, v.num());
    assert_eq!(&2, v.num());
}

#[EnumValued]
pub fn num<'lf, 'ot, const N: usize, const A: bool, T, O>(    number: &'static TypedEnum<'lf, 'ot, N, A, T, O>,) -> usize
where
    T:Into<u8>,
    T:Into<u8>,
    O:Into<u8>,
{
    match number {
        TypedEnum::Soft(_) => 1,
        TypedEnum::SoftTwo(_) => 2,
        TypedEnum::Middle(_) => 3,
        TypedEnum::Hard(_) => 4,
    }
}

#[derive(Debug, PartialEq)]
#[EnumIndexed(Consts(N: 8, A:true, T: u8, O: u8))]
enum TypedEnum<'lf, 'ot, const N: usize, const A: bool, T, O>
where
    T:Into<u8>,
    T:Into<u8>,
    O:Into<u8>,
{
    Soft(&'lf usize),
    SoftTwo(&'ot usize),
    Middle(O),
    Hard(T),
}

#[derive(Debug)]
#[EnumIndexed(NoFrom)]
enum WithInteriorMutability{
    Cell{cell:OnceCell<usize>},
    Mutex{mutex:Mutex<usize>}
}


#[allow(dead_code)]
#[derive(Debug)]
#[EnumIndexed(Consts(N: 8, T: u8))]
enum ParameterTypesAndEnumWithFields<'lf, const N: usize, T: Into<u8>> {
    First(&'lf &'lf T),
    Second(&'lf usize),
    Third(u8),
    NamedFieldsImplementingConst { n:u8,m: u8 },
    #[initialize_variant(n: 15,m: 5)]
    NamedFieldsImplementingConstWithNumbersInPos{ n:u8,m: u8 },
    UnnamedFieldsImplementingConst(u8, u8),
    #[initialize_variant(5, 15)]
    UnnamedFieldsImplementingConstWithNumbers(u8, u8),
    #[initialize_variant(1: 15,0: 5)]
    UnnamedFieldsImplementingConstWithNumbersInPos(u8, u8),
}