use crate::Candidate;
use crate::search::output::SearchOutput;
use crate::search::output::style::SearchSeparators;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LinkTraversal {
    DoNotFollow,
    Follow,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct WalkOptions {
    pub links: LinkTraversal,
    pub max_depth: Option<usize>,
    pub max_filesize: Option<u64>,
    pub one_file_system: bool,
}

impl Default for WalkOptions {
    fn default() -> Self {
        Self {
            links: LinkTraversal::DoNotFollow,
            max_depth: None,
            max_filesize: None,
            one_file_system: false,
        }
    }
}

#[derive(Clone)]
pub struct SearchExecution<'a> {
    pub candidates: Vec<Candidate>,
    pub output: SearchOutput,
    pub separators: &'a SearchSeparators,
    pub collect: SearchCollection,
}

/// Optional artifacts gathered during search beyond primary output.
#[must_use]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct SearchCollection {
    pub stats: bool,
    pub hits: bool,
}

impl Default for SearchCollection {
    fn default() -> Self {
        Self::none()
    }
}

impl SearchCollection {
    pub const fn none() -> Self {
        Self {
            stats: false,
            hits: false,
        }
    }

    pub const fn stats() -> Self {
        Self {
            stats: true,
            hits: false,
        }
    }

    pub const fn hits() -> Self {
        Self {
            stats: false,
            hits: true,
        }
    }

    pub const fn stats_and_hits() -> Self {
        Self {
            stats: true,
            hits: true,
        }
    }

    pub const fn with_stats(self, stats: bool) -> Self {
        Self {
            stats,
            hits: self.hits,
        }
    }

    pub const fn with_hits(self, hits: bool) -> Self {
        Self {
            stats: self.stats,
            hits,
        }
    }
}
