//! Presentation state for storage-provided decrypted search results.

use ironstorage::read::{GrepEntry, GrepResults};

#[derive(Debug)]
pub struct GrepView {
    results: GrepResults,
    selected: Option<usize>,
}

impl GrepView {
    pub fn new(results: GrepResults) -> Self {
        let selected = (!results.entries().is_empty()).then_some(0);
        Self { results, selected }
    }

    pub fn entries(&self) -> &[GrepEntry] {
        self.results.entries()
    }

    pub fn selected_index(&self) -> Option<usize> {
        self.selected
    }

    pub fn selected_entry(&self) -> Option<&GrepEntry> {
        self.selected
            .and_then(|index| self.results.entries().get(index))
    }

    pub fn includes_line_numbers(&self) -> bool {
        self.results.includes_line_numbers()
    }

    pub fn next(&mut self) {
        let count = self.results.entries().len();
        if count != 0 {
            self.selected = Some(self.selected.map_or(0, |index| (index + 1) % count));
        }
    }

    pub fn previous(&mut self) {
        let count = self.results.entries().len();
        if count != 0 {
            self.selected = Some(
                self.selected
                    .map_or(0, |index| index.checked_sub(1).unwrap_or(count - 1)),
            );
        }
    }
}
