Framework for embedding localizations into Rust types
//! End-to-end test for unnamed field support in the `l10n_embed_derive` macro

mod common;

use icu_locale::{Locale, locale};
use l10n_embed::Localize;
use l10n_embed_derive::localize;

const DEFAULT_LOCALE: Locale = locale!("en-US");
const EXPECTED_LOCALES: [Locale; 4] = [
    locale!("zh-CN"),
    locale!("en-US"),
    locale!("ja-JP"),
    locale!("fr"),
];

pub struct LocalizableType;

impl Localize for LocalizableType {
    fn available_locales(&self) -> Vec<Locale> {
        EXPECTED_LOCALES.to_vec()
    }

    fn localize_for(&self, locale: &Locale) -> String {
        format!("Localized with locale: {locale}")
    }
}

#[localize("tests/locale/**/basic.ftl")]
pub struct MessageStruct(LocalizableType);

#[localize("tests/locale/**/basic.ftl")]
pub enum MessageEnum {
    Greeting { name: String },
    Forward(LocalizableType),
}

mod forward {
    use super::common::compare_message;
    use super::{DEFAULT_LOCALE, EXPECTED_LOCALES, LocalizableType, MessageEnum, MessageStruct};
    use l10n_embed::Localize;
    use pretty_assertions::assert_eq;

    #[test]
    fn message() {
        let expected = "Localized with locale: en-US";

        compare_message(MessageStruct(LocalizableType), expected, DEFAULT_LOCALE);
        compare_message(
            MessageEnum::Forward(LocalizableType),
            expected,
            DEFAULT_LOCALE,
        );
    }

    #[test]
    fn available_locales() {
        let expected_locales = EXPECTED_LOCALES.to_vec();

        assert_eq!(
            expected_locales,
            MessageStruct(LocalizableType).available_locales()
        );
        assert_eq!(
            expected_locales,
            MessageEnum::Forward(LocalizableType).available_locales()
        );
    }
}

/// Ensure other enum variants are not affected
mod preserves_enum_variants {
    use super::common::compare_message;
    use super::{DEFAULT_LOCALE, LocalizableType, MessageEnum};
    use l10n_embed::Localize;
    use pretty_assertions::{assert_eq, assert_ne};

    #[test]
    fn message() {
        compare_message(
            MessageEnum::Greeting {
                name: String::from("Ferris"),
            },
            "Hello, Ferris!",
            DEFAULT_LOCALE,
        );
    }

    #[test]
    fn available_locales() {
        let greeting = MessageEnum::Greeting {
            name: String::from("Ferris"),
        };

        assert_ne!(
            greeting.available_locales(),
            MessageEnum::Forward(LocalizableType).available_locales()
        );
        assert_eq!(vec![DEFAULT_LOCALE], greeting.available_locales());
    }
}