//! Sorted Linked List

use std::{cell::Cell, cmp::Ordering, ptr};

use crate::utility_types::Delta;
pub(crate) unsafe trait Elem {
    fn prev(&self) -> &Cell<*const Self>;
    fn next(&self) -> &Cell<*const Self>;
    fn key(&self) -> &Cell<u32>;
}

pub(crate) enum AddToSllResult<'a, E: Elem> {
    NoHead,
    EmptyHead(&'a Cell<*const E>),
    SmallerThanHead(&'a Cell<*const E>),
    SmallerThanNotHead(*const E),
    AlreadyInSll(*const E),
}

impl<'a, E: Elem> AddToSllResult<'a, E> {
    pub(crate) fn add_to_sll(&self, elem_ptr: *const E) {
        unsafe {
            (*elem_ptr).prev().set(elem_ptr);
            (*elem_ptr).next().set(elem_ptr);

            match self {
                // Case 1: empty head, replace it.
                AddToSllResult::EmptyHead(head) => head.set(elem_ptr),

                // Case 2: we are smaller than the head, replace it.
                AddToSllResult::SmallerThanHead(head) => {
                    let old_head = head.get();
                    let prev = (*old_head).prev().replace(elem_ptr);
                    (*prev).next().set(elem_ptr);
                    (*elem_ptr).next().set(old_head);
                    (*elem_ptr).prev().set(prev);
                    head.set(elem_ptr);
                }

                // Case 3: insert in place found by looping
                AddToSllResult::SmallerThanNotHead(curr) => {
                    let next = (**curr).next().replace(elem_ptr);
                    (*next).prev().set(elem_ptr);
                    (*elem_ptr).prev().set(*curr);
                    (*elem_ptr).next().set(next);
                }
                AddToSllResult::NoHead | AddToSllResult::AlreadyInSll(_) => (),
            }
        }
    }
}

#[cold]
pub(crate) fn init<'a, E: Elem>(
    head: Option<&'a Cell<*const E>>,
    elem: &E,
) -> AddToSllResult<'a, E> {
    if let Some(head) = head {
        link(head, elem)
    } else {
        AddToSllResult::NoHead
    }
}

#[cold]
pub(crate) fn unlink<E: Elem>(head: &Cell<*const E>, elem: &E) {
    debug_assert!(!head.get().is_null(), "invalid linked list head");

    let elem_ptr: *const E = elem;

    let prev = elem.prev().replace(elem_ptr);
    let next = elem.next().replace(elem_ptr);
    unsafe {
        debug_assert_eq!((*prev).next().get(), elem_ptr, "invalid linked list links");
        debug_assert_eq!((*next).prev().get(), elem_ptr, "invalid linked list links");
        (*prev).next().set(next);
        (*next).prev().set(prev);
    }

    if head.get() == elem_ptr {
        head.set(if next == elem_ptr { ptr::null() } else { next })
    }
}

#[cold]
pub(crate) fn link<'a, E: Elem>(head: &'a Cell<*const E>, elem: &E) -> AddToSllResult<'a, E> {
    unsafe {
        let old_head = head.get();
        // Case 1: empty head, replace it.
        if old_head.is_null() {
            return AddToSllResult::EmptyHead(head);
        }

        // Case 2: we are smaller than the head, replace it.
        if elem.key() < (*old_head).key() {
            return AddToSllResult::SmallerThanHead(head);
        }

        // Case 3: loop *backward* until we find insertion place. Because of
        // Case 2, we can't loop beyond the head.
        let mut curr = (*old_head).prev().get();
        loop {
            match (*curr).key().cmp(elem.key()) {
                Ordering::Less => return AddToSllResult::SmallerThanNotHead(curr),
                Ordering::Equal => return AddToSllResult::AlreadyInSll(curr),
                Ordering::Greater => curr = (*curr).prev().get(),
            }
        }
    }
}

pub(crate) fn adjust<E: Elem>(elem: &E, from: u32, by: Delta<u32>) {
    let elem_ptr: *const E = elem;

    unsafe {
        let mut curr = elem_ptr;
        loop {
            let mut key = (*curr).key().get();
            if key >= from {
                key += by;
                (*curr).key().set(key);
            }
            curr = (*curr).next().get();
            if curr == elem_ptr {
                break;
            }
        }
    }
}
