use crate::{
    rope::atoms::{Atom, Atoms},
    utils::Utils,
};

pub struct Line<'r, 'a> {
    atoms: &'a mut Atoms<'r>,
    seen_newline: bool,
}

impl<'r, 'a> Line<'r, 'a> {
    const INITIAL_SEEN_NEWLINE: bool = false;

    pub const fn new(atoms: &'a mut Atoms<'r>) -> Self {
        let seen_newline = Self::INITIAL_SEEN_NEWLINE;

        Self { atoms, seen_newline }
    }

    pub fn advance(&mut self, count: usize) {
        if self.seen_newline {
            return;
        }

        let distance_advanced = self.atoms.advance_within_line(count).into_ok_err();

        if distance_advanced.length.extended_graphemes < count {
            self.atoms.advance_to_start_of_next_line().into_ok_err();
            self.seen_newline.set_true();
        }
    }
}

impl<'r> Iterator for Line<'r, '_> {
    type Item = Atom<'r>;

    fn next(&mut self) -> Option<Self::Item> {
        if self.seen_newline {
            return None;
        }

        let atom = self.atoms.next()?;

        if atom.extended_grapheme.is_newline() {
            self.seen_newline.set_true();
        }

        atom.some()
    }
}
