Framework for embedding localizations into Rust types
use super::macros::impl_with_default;
use crate::{InteractionEnvironment, InteractionError};
use l10n_embed::Localize;

pub struct Select<'environment> {
    environment: &'environment InteractionEnvironment,
    localized_prompt: String,
    default: Option<usize>,
    items: Option<Vec<String>>,
}

impl_with_default!(Select, usize);

impl<'environment> Select<'environment> {
    pub fn new<L: Localize>(environment: &'environment InteractionEnvironment, prompt: L) -> Self {
        let localized_prompt = prompt.localize_for(&environment.locale);

        Self {
            environment,
            localized_prompt,
            default: None,
            items: None,
        }
    }

    pub fn with_items<L: Localize>(mut self, items: &[L]) -> Self {
        let localized_items = items
            .iter()
            .map(|item| item.localize_for(&self.environment.locale))
            .collect::<Vec<String>>();

        self.items = Some(localized_items);
        self
    }

    pub fn interact(self) -> Result<Option<usize>, InteractionError> {
        match self.environment.context {
            crate::InteractionContext::Terminal => {
                let mut prompt = dialoguer::FuzzySelect::with_theme(&*super::THEME)
                    .with_prompt(self.localized_prompt);

                if let Some(default) = self.default {
                    prompt = prompt.default(default);
                }

                if let Some(items) = self.items {
                    prompt = prompt.items(&items);
                }

                Ok(Some(prompt.interact()?))
            }
            crate::InteractionContext::NonInteractive => Ok(None),
        }
    }
}