//! This crate contains a memoizer for internationalization formatters. Often it is
//! expensive (in terms of performance and memory) to construct a formatter, but then
//! relatively cheap to run the format operation.
//!
//! The [IntlMemoizer] is the main struct that creates a per-locale [IntlLangMemoizer].

use std::cell::RefCell;
use std::collections::hash_map::Entry;
use std::collections::HashMap;
use std::hash::Hash;
use std::rc::{Rc, Weak};
use unic_langid::LanguageIdentifier;

pub mod concurrent;

/// The trait that needs to be implemented for each intl formatter that needs to be
/// memoized.
pub trait Memoizable {
    /// Type of the arguments that are used to construct the formatter.
    type Args: 'static + Eq + Hash + Clone;

    /// Type of any errors that can occur during the construction process.
    type Error;

    /// Construct a formatter. This maps the [`Self::Args`] type to the actual constructor
    /// for an intl formatter.
    fn construct(lang: LanguageIdentifier, args: Self::Args) -> Result<Self, Self::Error>
    where
        Self: std::marker::Sized;
}

/// The [`IntlLangMemoizer`] can memoize multiple constructed internationalization
/// formatters, and their configuration for a single locale. For instance, given "en-US",
/// a memorizer could retain 3 DateTimeFormat instances, and a PluralRules.
///
/// For memoizing with multiple locales, see [`IntlMemoizer`].
///
/// # Example
///
/// The code example does the following steps:
///
/// 1. Create a static counter
/// 2. Create an `ExampleFormatter`
/// 3. Implement [`Memoizable`] for `ExampleFormatter`.
/// 4. Use `IntlLangMemoizer::with_try_get` to run `ExampleFormatter::format`
/// 5. Demonstrate the memoization using the static counter
///
/// ```
/// use intl_memoizer::{IntlLangMemoizer, Memoizable};
/// use unic_langid::LanguageIdentifier;
///
/// // Create a static counter so that we can demonstrate the side effects of when
/// // the memoizer re-constructs an API.
///
/// static mut INTL_EXAMPLE_CONSTRUCTS: u32 = 0;
/// fn increment_constructs() {
///     unsafe {
///         INTL_EXAMPLE_CONSTRUCTS += 1;
///     }
/// }
///
/// fn get_constructs_count() -> u32 {
///     unsafe { INTL_EXAMPLE_CONSTRUCTS }
/// }
///
/// /// Create an example formatter, that doesn't really do anything useful. In a real
/// /// implementation, this could be a PluralRules or DateTimeFormat struct.
/// struct ExampleFormatter {
///     lang: LanguageIdentifier,
///     /// This is here to show how to initiate the API with an argument.
///     prefix: String,
/// }
///
/// impl ExampleFormatter {
///     /// Perform an example format by printing information about the formatter
///     /// configuration, and the arguments passed into the individual format operation.
///     fn format(&self, example_string: &str) -> String {
///         format!(
///             "{} lang({}) string({})",
///             self.prefix, self.lang, example_string
///         )
///     }
/// }
///
/// /// Multiple classes of structs may be add1ed to the memoizer, with the restriction
/// /// that they must implement the `Memoizable` trait.
/// impl Memoizable for ExampleFormatter {
///     /// The arguments will be passed into the constructor. Here a single `String`
///     /// will be used as a prefix to the formatting operation.
///     type Args = (String,);
///
///     /// If the constructor is fallible, than errors can be described here.
///     type Error = ();
///
///     /// This function wires together the `Args` and `Error` type to construct
///     /// the intl API. In our example, there is
///     fn construct(lang: LanguageIdentifier, args: Self::Args) -> Result<Self, Self::Error> {
///         // Keep track for example purposes that this was constructed.
///         increment_constructs();
///
///         Ok(Self {
///             lang,
///             prefix: args.0,
///         })
///     }
/// }
///
/// // The following demonstrates how these structs are actually used with the memoizer.
///
/// // Construct a new memoizer.
/// let lang = "en-US".parse().expect("Failed to parse.");
/// let memoizer = IntlLangMemoizer::new(lang);
///
/// // These arguments are passed into the constructor for `ExampleFormatter`.
/// let construct_args = (String::from("prefix:"),);
/// let message1 = "The format operation will run";
/// let message2 = "ExampleFormatter will be re-used, when a second format is run";
///
/// // Run `IntlLangMemoizer::with_try_get`. The name of the method means "with" an
/// // intl formatter, "try and get" the result. See the method documentation for
/// // more details.
///
/// let result1 = memoizer
///     .with_try_get::<ExampleFormatter, _, _>(construct_args.clone(), |intl_example| {
///         intl_example.format(message1)
///     });
///
/// // The memoized instance of `ExampleFormatter` will be re-used.
/// let result2 = memoizer
///     .with_try_get::<ExampleFormatter, _, _>(construct_args.clone(), |intl_example| {
///         intl_example.format(message2)
///     });
///
/// assert_eq!(
///     result1.unwrap(),
///     "prefix: lang(en-US) string(The format operation will run)"
/// );
/// assert_eq!(
///     result2.unwrap(),
///     "prefix: lang(en-US) string(ExampleFormatter will be re-used, when a second format is run)"
/// );
/// assert_eq!(
///     get_constructs_count(),
///     1,
///     "The constructor was only run once."
/// );
///
/// let construct_args = (String::from("re-init:"),);
///
/// // Since the constructor args changed, `ExampleFormatter` will be re-constructed.
/// let result1 = memoizer
///     .with_try_get::<ExampleFormatter, _, _>(construct_args.clone(), |intl_example| {
///         intl_example.format(message1)
///     });
///
/// // The memoized instance of `ExampleFormatter` will be re-used.
/// let result2 = memoizer
///     .with_try_get::<ExampleFormatter, _, _>(construct_args.clone(), |intl_example| {
///         intl_example.format(message2)
///     });
///
/// assert_eq!(
///     result1.unwrap(),
///     "re-init: lang(en-US) string(The format operation will run)"
/// );
/// assert_eq!(
///     result2.unwrap(),
///     "re-init: lang(en-US) string(ExampleFormatter will be re-used, when a second format is run)"
/// );
/// assert_eq!(
///     get_constructs_count(),
///     2,
///     "The constructor was invalidated and ran again."
/// );
/// ```
#[derive(Debug)]
pub struct IntlLangMemoizer {
    lang: LanguageIdentifier,
    map: RefCell<type_map::TypeMap>,
}

impl IntlLangMemoizer {
    /// Create a new [`IntlLangMemoizer`] that is unique to a specific
    /// [`LanguageIdentifier`]
    pub fn new(lang: LanguageIdentifier) -> Self {
        Self {
            lang,
            map: RefCell::new(type_map::TypeMap::new()),
        }
    }

    /// `with_try_get` means `with` an internationalization formatter, `try` and `get` a result.
    /// The (potentially expensive) constructor for the formatter (such as PluralRules or
    /// DateTimeFormat) will be memoized and only constructed once for a given
    /// `construct_args`. After that the format operation can be run multiple times
    /// inexpensively.
    ///
    /// The first generic argument `I` must be provided, but the `R` and `U` will be
    /// deduced by the typing of the `callback` argument that is provided.
    ///
    /// I - The memoizable intl object, for instance a `PluralRules` instance. This
    ///     must implement the Memoizable trait.
    ///
    /// R - The return result from the callback `U`.
    ///
    /// U - The callback function. Takes an instance of `I` as the first parameter and
    ///     returns the R value.
    pub fn with_try_get<I, R, U>(&self, construct_args: I::Args, callback: U) -> Result<R, I::Error>
    where
        Self: Sized,
        I: Memoizable + 'static,
        U: FnOnce(&I) -> R,
    {
        let mut map = self
            .map
            .try_borrow_mut()
            .expect("Cannot use memoizer reentrantly");
        let cache = map
            .entry::<HashMap<I::Args, I>>()
            .or_insert_with(HashMap::new);

        let e = match cache.entry(construct_args.clone()) {
            Entry::Occupied(entry) => entry.into_mut(),
            Entry::Vacant(entry) => {
                let val = I::construct(self.lang.clone(), construct_args)?;
                entry.insert(val)
            }
        };
        Ok(callback(e))
    }
}

/// [`IntlMemoizer`] is designed to handle lazily-initialized references to
/// internationalization formatters.
///
/// Constructing a new formatter is often expensive in terms of memory and performance,
/// and the instance is often read-only during its lifetime. The format operations in
/// comparison are relatively cheap.
///
/// Because of this relationship, it can be helpful to memoize the constructors, and
/// re-use them across multiple format operations. This strategy is used where all
/// instances of intl APIs such as `PluralRules`, `DateTimeFormat` etc. are memoized
/// between all `FluentBundle` instances.
///
/// # Example
///
/// For a more complete example of the memoization, see the [`IntlLangMemoizer`] documentation.
/// This example provides a higher-level overview.
///
/// ```
/// # use intl_memoizer::{IntlMemoizer, IntlLangMemoizer, Memoizable};
/// # use unic_langid::LanguageIdentifier;
/// # use std::rc::Rc;
/// #
/// # struct ExampleFormatter {
/// #     lang: LanguageIdentifier,
/// #     prefix: String,
/// # }
/// #
/// # impl ExampleFormatter {
/// #     fn format(&self, example_string: &str) -> String {
/// #         format!(
/// #             "{} lang({}) string({})",
/// #             self.prefix, self.lang, example_string
/// #         )
/// #     }
/// # }
/// #
/// # impl Memoizable for ExampleFormatter {
/// #     type Args = (String,);
/// #     type Error = ();
/// #     fn construct(lang: LanguageIdentifier, args: Self::Args) -> Result<Self, Self::Error> {
/// #         Ok(Self {
/// #             lang,
/// #             prefix: args.0,
/// #         })
/// #     }
/// # }
/// #
/// let mut memoizer = IntlMemoizer::default();
///
/// // The memoziation happens per-locale.
/// let en_us = "en-US".parse().expect("Failed to parse.");
/// let en_us_memoizer: Rc<IntlLangMemoizer> = memoizer.get_for_lang(en_us);
///
/// // These arguments are passed into the constructor for `ExampleFormatter`. The
/// // construct_args will be used for determining the memoization, but the message
/// // can be different and re-use the constructed instance.
/// let construct_args = (String::from("prefix:"),);
/// let message = "The format operation will run";
///
/// // Use the `ExampleFormatter` from the `IntlLangMemoizer` example. It returns a
/// // string that demonstrates the configuration of the formatter. This step will
/// // construct a new formatter if needed, and run the format operation.
/// //
/// // See `IntlLangMemoizer` for more details on this step.
/// let en_us_result = en_us_memoizer
///     .with_try_get::<ExampleFormatter, _, _>(construct_args.clone(), |intl_example| {
///         intl_example.format(message)
///     });
///
/// // The example formatter constructs a string with diagnostic information about
/// // the configuration.
/// assert_eq!(
///     en_us_result.unwrap(),
///     "prefix: lang(en-US) string(The format operation will run)"
/// );
///
/// // The process can be repeated for a new locale.
///
/// let de_de = "de-DE".parse().expect("Failed to parse.");
/// let de_de_memoizer: Rc<IntlLangMemoizer> = memoizer.get_for_lang(de_de);
///
/// let de_de_result = de_de_memoizer
///     .with_try_get::<ExampleFormatter, _, _>(construct_args.clone(), |intl_example| {
///         intl_example.format(message)
///     });
///
/// assert_eq!(
///     de_de_result.unwrap(),
///     "prefix: lang(de-DE) string(The format operation will run)"
/// );
/// ```
#[derive(Default)]
pub struct IntlMemoizer {
    map: HashMap<LanguageIdentifier, Weak<IntlLangMemoizer>>,
}

impl IntlMemoizer {
    /// Get a [`IntlLangMemoizer`] for a given language. If one does not exist for
    /// a locale, it will be constructed and weakly retained. See [`IntlLangMemoizer`]
    /// for more detailed documentation how to use it.
    pub fn get_for_lang(&mut self, lang: LanguageIdentifier) -> Rc<IntlLangMemoizer> {
        match self.map.entry(lang.clone()) {
            Entry::Vacant(empty) => {
                let entry = Rc::new(IntlLangMemoizer::new(lang));
                empty.insert(Rc::downgrade(&entry));
                entry
            }
            Entry::Occupied(mut entry) => {
                if let Some(entry) = entry.get().upgrade() {
                    entry
                } else {
                    let e = Rc::new(IntlLangMemoizer::new(lang));
                    entry.insert(Rc::downgrade(&e));
                    e
                }
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use fluent_langneg::{negotiate_languages, NegotiationStrategy};
    use intl_pluralrules::{PluralCategory, PluralRuleType, PluralRules as IntlPluralRules};
    use std::{sync::Arc, thread};

    struct PluralRules(pub IntlPluralRules);

    impl PluralRules {
        pub fn new(
            lang: LanguageIdentifier,
            pr_type: PluralRuleType,
        ) -> Result<Self, &'static str> {
            let default_lang: LanguageIdentifier = "en".parse().unwrap();
            let pr_lang = negotiate_languages(
                &[lang],
                &IntlPluralRules::get_locales(pr_type),
                Some(&default_lang),
                NegotiationStrategy::Lookup,
            )[0]
            .clone();

            Ok(Self(IntlPluralRules::create(pr_lang, pr_type)?))
        }
    }

    impl Memoizable for PluralRules {
        type Args = (PluralRuleType,);
        type Error = &'static str;
        fn construct(lang: LanguageIdentifier, args: Self::Args) -> Result<Self, Self::Error> {
            Self::new(lang, args.0)
        }
    }

    #[test]
    fn test_single_thread() {
        let lang: LanguageIdentifier = "en".parse().unwrap();

        let mut memoizer = IntlMemoizer::default();
        {
            let en_memoizer = memoizer.get_for_lang(lang.clone());

            let result = en_memoizer
                .with_try_get::<PluralRules, _, _>((PluralRuleType::CARDINAL,), |cb| cb.0.select(5))
                .unwrap();
            assert_eq!(result, Ok(PluralCategory::OTHER));
        }

        {
            let en_memoizer = memoizer.get_for_lang(lang);

            let result = en_memoizer
                .with_try_get::<PluralRules, _, _>((PluralRuleType::CARDINAL,), |cb| cb.0.select(5))
                .unwrap();
            assert_eq!(result, Ok(PluralCategory::OTHER));
        }
    }

    #[test]
    fn test_concurrent() {
        let lang: LanguageIdentifier = "en".parse().unwrap();
        let memoizer = Arc::new(concurrent::IntlLangMemoizer::new(lang));
        let mut threads = vec![];

        // Spawn four threads that all use the PluralRules.
        for _ in 0..4 {
            let memoizer = Arc::clone(&memoizer);
            threads.push(thread::spawn(move || {
                memoizer
                    .with_try_get::<PluralRules, _, _>((PluralRuleType::CARDINAL,), |cb| {
                        cb.0.select(5)
                    })
                    .expect("Failed to get a PluralRules result.")
            }));
        }

        for thread in threads.drain(..) {
            let result = thread.join().expect("Failed to join thread.");
            assert_eq!(result, Ok(PluralCategory::OTHER));
        }
    }
}
