use crate::model::{Bank, Pattern};

const MAX_UNDO: usize = 100;

pub enum UndoScope {
    Pattern {
        bank: usize,
        pattern: usize,
        data: Pattern,
    },
    Bank {
        bank: usize,
        data: Bank,
    },
}

pub struct UndoEntry {
    pub scope: UndoScope,
    pub cursor: (usize, usize, usize),
}

#[derive(Default)]
pub struct UndoHistory {
    pub(crate) undo_stack: Vec<UndoEntry>,
    redo_stack: Vec<UndoEntry>,
}

impl UndoHistory {
    pub fn push(&mut self, entry: UndoEntry) {
        self.redo_stack.clear();
        if self.undo_stack.len() >= MAX_UNDO {
            self.undo_stack.remove(0);
        }
        self.undo_stack.push(entry);
    }

    pub fn pop_undo(&mut self) -> Option<UndoEntry> {
        self.undo_stack.pop()
    }

    pub fn push_redo(&mut self, entry: UndoEntry) {
        self.redo_stack.push(entry);
    }

    pub fn pop_redo(&mut self) -> Option<UndoEntry> {
        self.redo_stack.pop()
    }

    pub fn clear(&mut self) {
        self.undo_stack.clear();
        self.redo_stack.clear();
    }
}
