use crate::command::{CommandExecutor, EditorCommand};
use crate::error::CoreResult;
use crate::model::DocumentModel;

#[derive(Debug, Clone)]
pub struct EditorSession {
    document: DocumentModel,
    undo_stack: Vec<DocumentModel>,
    redo_stack: Vec<DocumentModel>,
}

impl EditorSession {
    pub fn new(document: DocumentModel) -> Self {
        Self {
            document,
            undo_stack: Vec::new(),
            redo_stack: Vec::new(),
        }
    }

    pub fn document(&self) -> &DocumentModel {
        &self.document
    }

    pub fn apply_command(&mut self, command: EditorCommand) -> CoreResult<()> {
        let snapshot = self.document.clone();
        CommandExecutor::apply(&mut self.document, command)?;
        self.undo_stack.push(snapshot);
        self.redo_stack.clear();
        Ok(())
    }

    pub fn undo(&mut self) -> bool {
        let Some(previous) = self.undo_stack.pop() else {
            return false;
        };
        self.redo_stack.push(self.document.clone());
        self.document = previous;
        true
    }

    pub fn redo(&mut self) -> bool {
        let Some(next) = self.redo_stack.pop() else {
            return false;
        };
        self.undo_stack.push(self.document.clone());
        self.document = next;
        true
    }
}
