use crate::journal::JournalId;
use std::collections::hash_map::HashMap;

struct StartListEntry {
    next: Option<JournalId>,
    prev: Option<JournalId>,
}

impl StartListEntry {
    pub fn new(prev: Option<JournalId>) -> StartListEntry {
        StartListEntry { next: None, prev }
    }
}

pub(super) struct StartList {
    transactions: HashMap<JournalId, StartListEntry>,
    last: Option<JournalId>,
}

impl StartList {
    pub(super) fn new() -> StartList {
        StartList {
            transactions: HashMap::new(),
            last: None,
        }
    }

    pub(super) fn push(&mut self, id: &JournalId) {
        self.transactions
            .insert(id.clone(), StartListEntry::new(self.last.clone()));
        if let Some(ref lst) = self.last {
            self.transactions.get_mut(lst).unwrap().next = Some(id.clone());
        }
        self.last = Some(id.clone());
    }

    pub(super) fn remove(&mut self, id: &JournalId) -> bool {
        if let Some(entry) = self.transactions.remove(id) {
            if let Some(ref next) = entry.next {
                self.transactions.get_mut(next).unwrap().prev = entry.prev.clone();
            }
            if let Some(ref prev) = entry.prev {
                self.transactions.get_mut(prev).unwrap().next = entry.next.clone();
            }
            if let Some(ref l) = self.last {
                if l == id {
                    self.last = entry.prev.clone();
                }
            }
            entry.prev.is_none()
        } else {
            false
        }
    }

    pub(super) fn is_page_in_start_list(&self, page: u64) -> bool {
        for k in self.transactions.keys() {
            if k.page == page {
                return true;
            }
        }
        false
    }
}
