//! Kill Ring management
use line_buffer::{DeleteListener, Direction};

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum Action {
    Kill,
    Yank(usize),
    Other,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Mode {
    Append,
    Prepend,
}

pub struct KillRing {
    slots: Vec<String>,
    // where we are in the kill ring
    index: usize,
    // whether or not the last command was a kill or a yank
    last_action: Action,
    killing: bool,
}

impl KillRing {
    /// Create a new kill-ring of the given `size`.
    pub fn new(size: usize) -> KillRing {
        KillRing {
            slots: Vec::with_capacity(size),
            index: 0,
            last_action: Action::Other,
            killing: false,
        }
    }

    /// Reset `last_action` state.
    pub fn reset(&mut self) {
        self.last_action = Action::Other;
    }

    /// Add `text` to the kill-ring.
    pub fn kill(&mut self, text: &str, dir: Mode) {
        if let Action::Kill = self.last_action {
            if self.slots.capacity() == 0 {
                // disabled
                return;
            }
            match dir {
                Mode::Append => self.slots[self.index].push_str(text),
                Mode::Prepend => self.slots[self.index].insert_str(0, text),
            };
        } else {
            self.last_action = Action::Kill;
            if self.slots.capacity() == 0 {
                // disabled
                return;
            }
            if self.index == self.slots.capacity() - 1 {
                // full
                self.index = 0;
            } else if !self.slots.is_empty() {
                self.index += 1;
            }
            if self.index == self.slots.len() {
                self.slots.push(String::from(text))
            } else {
                self.slots[self.index] = String::from(text);
            }
        }
    }

    /// Yank previously killed text.
    /// Return `None` when kill-ring is empty.
    pub fn yank(&mut self) -> Option<&String> {
        if self.slots.is_empty() {
            None
        } else {
            self.last_action = Action::Yank(self.slots[self.index].len());
            Some(&self.slots[self.index])
        }
    }

    /// Yank killed text stored in previous slot.
    /// Return `None` when the previous command was not a yank.
    pub fn yank_pop(&mut self) -> Option<(usize, &String)> {
        match self.last_action {
            Action::Yank(yank_size) => {
                if self.slots.is_empty() {
                    return None;
                }
                if self.index == 0 {
                    self.index = self.slots.len() - 1;
                } else {
                    self.index -= 1;
                }
                self.last_action = Action::Yank(self.slots[self.index].len());
                Some((yank_size, &self.slots[self.index]))
            }
            _ => None,
        }
    }
}

impl DeleteListener for KillRing {
    fn start_killing(&mut self) {
        self.killing = true;
    }

    fn delete(&mut self, _: usize, string: &str, dir: Direction) {
        if !self.killing {
            return;
        }
        let mode = match dir {
            Direction::Forward => Mode::Append,
            Direction::Backward => Mode::Prepend,
        };
        self.kill(string, mode);
    }

    fn stop_killing(&mut self) {
        self.killing = false;
    }
}

#[cfg(test)]
mod tests {
    use super::{Action, KillRing, Mode};

    #[test]
    fn disabled() {
        let mut kill_ring = KillRing::new(0);
        kill_ring.kill("text", Mode::Append);
        assert!(kill_ring.slots.is_empty());
        assert_eq!(0, kill_ring.index);
        assert_eq!(Action::Kill, kill_ring.last_action);

        assert_eq!(None, kill_ring.yank());
        assert_eq!(Action::Kill, kill_ring.last_action);
    }

    #[test]
    fn one_kill() {
        let mut kill_ring = KillRing::new(2);
        kill_ring.kill("word1", Mode::Append);
        assert_eq!(0, kill_ring.index);
        assert_eq!(1, kill_ring.slots.len());
        assert_eq!("word1", kill_ring.slots[0]);
        assert_eq!(Action::Kill, kill_ring.last_action);
    }

    #[test]
    fn kill_append() {
        let mut kill_ring = KillRing::new(2);
        kill_ring.kill("word1", Mode::Append);
        kill_ring.kill(" word2", Mode::Append);
        assert_eq!(0, kill_ring.index);
        assert_eq!(1, kill_ring.slots.len());
        assert_eq!("word1 word2", kill_ring.slots[0]);
        assert_eq!(Action::Kill, kill_ring.last_action);
    }

    #[test]
    fn kill_backward() {
        let mut kill_ring = KillRing::new(2);
        kill_ring.kill("word1", Mode::Prepend);
        kill_ring.kill("word2 ", Mode::Prepend);
        assert_eq!(0, kill_ring.index);
        assert_eq!(1, kill_ring.slots.len());
        assert_eq!("word2 word1", kill_ring.slots[0]);
        assert_eq!(Action::Kill, kill_ring.last_action);
    }

    #[test]
    fn kill_other_kill() {
        let mut kill_ring = KillRing::new(2);
        kill_ring.kill("word1", Mode::Append);
        kill_ring.reset();
        kill_ring.kill("word2", Mode::Append);
        assert_eq!(1, kill_ring.index);
        assert_eq!(2, kill_ring.slots.len());
        assert_eq!("word1", kill_ring.slots[0]);
        assert_eq!("word2", kill_ring.slots[1]);
        assert_eq!(Action::Kill, kill_ring.last_action);
    }

    #[test]
    fn many_kill() {
        let mut kill_ring = KillRing::new(2);
        kill_ring.kill("word1", Mode::Append);
        kill_ring.reset();
        kill_ring.kill("word2", Mode::Append);
        kill_ring.reset();
        kill_ring.kill("word3", Mode::Append);
        kill_ring.reset();
        kill_ring.kill("word4", Mode::Append);
        assert_eq!(1, kill_ring.index);
        assert_eq!(2, kill_ring.slots.len());
        assert_eq!("word3", kill_ring.slots[0]);
        assert_eq!("word4", kill_ring.slots[1]);
        assert_eq!(Action::Kill, kill_ring.last_action);
    }

    #[test]
    fn yank() {
        let mut kill_ring = KillRing::new(2);
        kill_ring.kill("word1", Mode::Append);
        kill_ring.reset();
        kill_ring.kill("word2", Mode::Append);

        assert_eq!(Some(&"word2".to_owned()), kill_ring.yank());
        assert_eq!(Action::Yank(5), kill_ring.last_action);
        assert_eq!(Some(&"word2".to_owned()), kill_ring.yank());
        assert_eq!(Action::Yank(5), kill_ring.last_action);
    }

    #[test]
    fn yank_pop() {
        let mut kill_ring = KillRing::new(2);
        kill_ring.kill("word1", Mode::Append);
        kill_ring.reset();
        kill_ring.kill("longword2", Mode::Append);

        assert_eq!(None, kill_ring.yank_pop());
        kill_ring.yank();
        assert_eq!(Some((9, &"word1".to_owned())), kill_ring.yank_pop());
        assert_eq!(Some((5, &"longword2".to_owned())), kill_ring.yank_pop());
        assert_eq!(Some((9, &"word1".to_owned())), kill_ring.yank_pop());
    }
}
