//! 侵入式双向链表测试
#![allow(unsafe_code)]

use moa_unsafe_list::{UnsafeListHead, UnsafeListNode, define_unsafe_list_head};

struct Node {
    val: usize,
    list: UnsafeListNode<Node>,
}

impl Node {
    fn create(val: usize) -> Self {
        Self { val, list: UnsafeListNode::new() }
    }
}

type NodeList = UnsafeListHead<Node, { core::mem::offset_of!(Node, list) }>;

fn collect_vals(head: &NodeList) -> Vec<usize> {
    head.iter().map(|n| n.val).collect()
}

fn collect_vals_rev(head: &NodeList) -> Vec<usize> {
    head.iter().rev().map(|n| n.val).collect()
}

// ── 基础操作 ──

#[test]
fn empty_list() {
    unsafe {
        define_unsafe_list_head!(head, Node, list);
        assert!(head.list_empty());
        assert!(head.list_empty_careful());
        assert!(head.list_first_entry_or_null().is_none());
        assert!(head.list_first_entry_or_null_mut().is_none());
    }
}

#[test]
fn list_add_front() {
    unsafe {
        define_unsafe_list_head!(head, Node, list);
        let mut a = Node::create(1);
        let mut b = Node::create(2);
        let mut c = Node::create(3);
        head.list_add(&mut a.list);
        head.list_add(&mut b.list);
        head.list_add(&mut c.list);

        assert!(!head.list_empty());
        assert_eq!(collect_vals(&head), [3, 2, 1]);
    }
}

#[test]
fn list_add_tail() {
    unsafe {
        define_unsafe_list_head!(head, Node, list);
        let mut a = Node::create(1);
        let mut b = Node::create(2);
        let mut c = Node::create(3);
        head.list_add_tail(&mut a.list);
        head.list_add_tail(&mut b.list);
        head.list_add_tail(&mut c.list);

        assert_eq!(collect_vals(&head), [1, 2, 3]);
    }
}

// ── entry 访问 ──

#[test]
fn first_and_last_entry() {
    unsafe {
        define_unsafe_list_head!(head, Node, list);
        let mut a = Node::create(10);
        let mut b = Node::create(20);
        let mut c = Node::create(30);
        head.list_add_tail(&mut a.list);
        head.list_add_tail(&mut b.list);
        head.list_add_tail(&mut c.list);

        assert_eq!(head.list_first_entry().val, 10);
        assert_eq!(head.list_last_entry().val, 30);
        assert_eq!(head.list_first_entry_mut().val, 10);
        assert_eq!(head.list_last_entry_mut().val, 30);
    }
}

#[test]
fn first_entry_or_null() {
    unsafe {
        define_unsafe_list_head!(head, Node, list);
        assert!(head.list_first_entry_or_null().is_none());
        assert!(head.list_first_entry_or_null_mut().is_none());

        let mut a = Node::create(42);
        head.list_add(&mut a.list);
        assert_eq!(head.list_first_entry_or_null().unwrap().val, 42);
        assert_eq!(head.list_first_entry_or_null_mut().unwrap().val, 42);
    }
}

// ── list_is_last ──

#[test]
fn list_is_last() {
    unsafe {
        define_unsafe_list_head!(head, Node, list);
        let mut a = Node::create(1);
        let mut b = Node::create(2);
        head.list_add_tail(&mut a.list);
        head.list_add_tail(&mut b.list);

        assert!(!head.list_is_last(&a.list));
        assert!(head.list_is_last(&b.list));
    }
}

// ── list_del ──

#[test]
fn list_del() {
    unsafe {
        define_unsafe_list_head!(head, Node, list);
        let mut a = Node::create(1);
        let mut b = Node::create(2);
        let mut c = Node::create(3);
        head.list_add_tail(&mut a.list);
        head.list_add_tail(&mut b.list);
        head.list_add_tail(&mut c.list);

        b.list.list_del();
        assert_eq!(collect_vals(&head), [1, 3]);

        a.list.list_del();
        assert_eq!(collect_vals(&head), [3]);

        c.list.list_del();
        assert!(head.list_empty());
    }
}

#[test]
fn list_del_init() {
    unsafe {
        define_unsafe_list_head!(head, Node, list);
        let mut a = Node::create(1);
        let mut b = Node::create(2);
        head.list_add_tail(&mut a.list);
        head.list_add_tail(&mut b.list);

        a.list.list_del_init();
        assert_eq!(collect_vals(&head), [2]);

        head.list_add(&mut a.list);
        assert_eq!(collect_vals(&head), [1, 2]);
    }
}

// ── list_replace ──

#[test]
fn list_replace() {
    unsafe {
        define_unsafe_list_head!(head, Node, list);
        let mut a = Node::create(1);
        let mut b = Node::create(2);
        let mut c = Node::create(99);
        head.list_add_tail(&mut a.list);
        head.list_add_tail(&mut b.list);

        a.list.list_replace(&mut c.list);
        assert_eq!(collect_vals(&head), [99, 2]);
    }
}

#[test]
fn list_replace_init() {
    unsafe {
        define_unsafe_list_head!(head, Node, list);
        let mut a = Node::create(1);
        let mut b = Node::create(2);
        let mut c = Node::create(99);
        head.list_add_tail(&mut a.list);
        head.list_add_tail(&mut b.list);

        a.list.list_replace_init(&mut c.list);
        assert_eq!(collect_vals(&head), [99, 2]);

        head.list_add(&mut a.list);
        assert_eq!(collect_vals(&head), [1, 99, 2]);
    }
}

// ── list_move ──

#[test]
fn list_move() {
    unsafe {
        define_unsafe_list_head!(head1, Node, list);
        define_unsafe_list_head!(head2, Node, list);
        let mut a = Node::create(1);
        let mut b = Node::create(2);
        let mut c = Node::create(3);
        head1.list_add_tail(&mut a.list);
        head1.list_add_tail(&mut b.list);
        head1.list_add_tail(&mut c.list);

        b.list.list_move(&mut head2);
        assert_eq!(collect_vals(&head1), [1, 3]);
        assert_eq!(collect_vals(&head2), [2]);
    }
}

#[test]
fn list_move_tail() {
    unsafe {
        define_unsafe_list_head!(head1, Node, list);
        define_unsafe_list_head!(head2, Node, list);
        let mut a = Node::create(1);
        let mut b = Node::create(2);
        head1.list_add_tail(&mut a.list);
        head1.list_add_tail(&mut b.list);

        let mut c = Node::create(3);
        head2.list_add(&mut c.list);

        a.list.list_move_tail(&mut head2);
        assert_eq!(collect_vals(&head1), [2]);
        assert_eq!(collect_vals(&head2), [3, 1]);
    }
}

// ── list_empty_careful ──

#[test]
fn list_empty_careful() {
    unsafe {
        define_unsafe_list_head!(head, Node, list);
        assert!(head.list_empty_careful());

        let mut a = Node::create(1);
        head.list_add(&mut a.list);
        assert!(!head.list_empty_careful());

        a.list.list_del();
        assert!(head.list_empty());
        assert!(head.list_empty_careful());
    }
}

// ── 迭代器 ──

#[test]
fn iter_forward_and_reverse() {
    unsafe {
        define_unsafe_list_head!(head, Node, list);
        let mut a = Node::create(1);
        let mut b = Node::create(2);
        let mut c = Node::create(3);
        head.list_add_tail(&mut a.list);
        head.list_add_tail(&mut b.list);
        head.list_add_tail(&mut c.list);

        assert_eq!(collect_vals(&head), [1, 2, 3]);
        assert_eq!(collect_vals_rev(&head), [3, 2, 1]);
    }
}

#[test]
fn iter_mut_forward() {
    unsafe {
        define_unsafe_list_head!(head, Node, list);
        let mut a = Node::create(1);
        let mut b = Node::create(2);
        let mut c = Node::create(3);
        head.list_add_tail(&mut a.list);
        head.list_add_tail(&mut b.list);
        head.list_add_tail(&mut c.list);

        for node in &mut head {
            node.val *= 10;
        }
        assert_eq!(collect_vals(&head), [10, 20, 30]);
    }
}

#[test]
fn iter_mut_reverse() {
    unsafe {
        define_unsafe_list_head!(head, Node, list);
        let mut a = Node::create(1);
        let mut b = Node::create(2);
        let mut c = Node::create(3);
        head.list_add_tail(&mut a.list);
        head.list_add_tail(&mut b.list);
        head.list_add_tail(&mut c.list);

        let vals: Vec<usize> = head.iter_mut().rev().map(|n| n.val).collect();
        assert_eq!(vals, [3, 2, 1]);
    }
}

#[test]
fn iter_empty_list() {
    define_unsafe_list_head!(head, Node, list);
    assert_eq!(collect_vals(&head), Vec::<usize>::new());
    assert_eq!(collect_vals_rev(&head), Vec::<usize>::new());
    let vals: Vec<usize> = head.iter_mut().map(|n| n.val).collect();
    assert_eq!(vals, Vec::<usize>::new());
    let vals: Vec<usize> = head.iter_mut().rev().map(|n| n.val).collect();
    assert_eq!(vals, Vec::<usize>::new());
}

#[test]
fn iter_single_element() {
    unsafe {
        define_unsafe_list_head!(head, Node, list);
        let mut a = Node::create(42);
        head.list_add(&mut a.list);

        assert_eq!(collect_vals(&head), [42]);
        assert_eq!(collect_vals_rev(&head), [42]);
    }
}

#[test]
fn init_manual() {
    unsafe {
        let mut head = NodeList::new();
        head.init_list_head();
        assert!(head.list_empty());

        let mut a = Node::create(1);
        head.list_add(&mut a.list);
        assert_eq!(head.list_first_entry().val, 1);
    }
}

#[test]
fn define_macro() {
    unsafe {
        define_unsafe_list_head!(head, Node, list);
        assert!(head.list_empty());

        let mut a = Node::create(1);
        head.list_add(&mut a.list);
        assert_eq!(head.list_first_entry().val, 1);
    }
}
