use crate::List::{Cons, Nil};
use std::cell::RefCell;
use std::rc::Rc;

#[derive(Debug)]
enum List {
    Cons(i32, RefCell<Rc<List>>),
    Nil,
}

impl List {
    fn tail(&self) -> Option<&RefCell<Rc<List>>> {
        match self {
            Cons(_, item) => Some(item),
            Nil => None,
        }
    }
}

// ANCHOR: here
fn main() {
    let a = Rc::new(Cons(5, RefCell::new(Rc::new(Nil))));

    println!("początkowy licznik rc dla a = {}", Rc::strong_count(&a));
    println!("następny element a = {:?}", a.tail());

    let b = Rc::new(Cons(10, RefCell::new(Rc::clone(&a))));

    println!("licznik rc dla a po utworzeniu b = {}", Rc::strong_count(&a));
    println!("początkowy licznik rc dla b = {}", Rc::strong_count(&b));
    println!("następny element b = {:?}", b.tail());

    if let Some(link) = a.tail() {
        *link.borrow_mut() = Rc::clone(&b);
    }

    println!("licznik rc dla b po zmianie a = {}", Rc::strong_count(&b));
    println!("licznik rc dla a po zmianie a = {}", Rc::strong_count(&a));

    // Odkomentuj następną linię, aby zobaczyć, że mamy cykl,
    // który doprowadzi do przepełnienia stosu
    // println!("następny element a = {:?}", a.tail());
}
// ANCHOR_END: here
