Framework for embedding localizations into Rust types
mod editor;
mod progress;
mod prompt;

use std::sync::Arc;

use indicatif::MultiProgress;
use l10n_embed::{Context, Localize};
use thiserror::Error;

pub use editor::Editor;
pub use progress::ProgressBar;
pub use prompt::{Confirm, Input, Password, Select};

enum InteractionContext {
    Terminal,
    NonInteractive,
}

#[derive(Debug, Error)]
pub enum InteractionError {
    #[error(transparent)]
    IO(std::io::Error),
}

impl From<std::io::Error> for InteractionError {
    fn from(value: std::io::Error) -> Self {
        Self::IO(value)
    }
}

impl From<dialoguer::Error> for InteractionError {
    fn from(value: dialoguer::Error) -> Self {
        match value {
            dialoguer::Error::IO(error) => Self::IO(error),
        }
    }
}

pub struct InteractionEnvironment {
    localization_context: Arc<Context>,
    interaction_context: InteractionContext,
    progress_bars: MultiProgress,
}

impl InteractionEnvironment {
    #[must_use]
    pub fn new(localization_context: Arc<Context>, interactive: bool) -> Self {
        Self {
            localization_context,
            interaction_context: if interactive {
                InteractionContext::Terminal
            } else {
                InteractionContext::NonInteractive
            },
            progress_bars: MultiProgress::new(),
        }
    }

    pub fn emit_message<L: Localize>(&self, message: L) -> Result<(), InteractionError> {
        let mut localized_message = String::new();
        message.localize(&self.localization_context, &mut localized_message);

        self.progress_bars.println(localized_message)?;

        Ok(())
    }
}