use wxdragon::id::{ID_OK, ID_YES};
use wxdragon::prelude::*;

pub(crate) fn show_yes_no_dialog_with_parent(
    parent: &dyn WxWidget,
    caption: &str,
    message: &str,
) -> bool {
    let dialog = MessageDialog::builder(parent, message, caption)
        .with_style(MessageDialogStyle::YesNo | MessageDialogStyle::IconQuestion)
        .build();
    dialog.show_modal() == ID_YES
}

pub(crate) fn show_error_dialog_with_parent(parent: &dyn WxWidget, caption: &str, message: &str) {
    let dialog = MessageDialog::builder(parent, message, caption)
        .with_style(MessageDialogStyle::OK | MessageDialogStyle::IconError)
        .build();
    let _ = dialog.show_modal();
}

pub(crate) fn show_info_dialog_with_parent(parent: &dyn WxWidget, caption: &str, message: &str) {
    let dialog = MessageDialog::builder(parent, message, caption)
        .with_style(MessageDialogStyle::OK | MessageDialogStyle::IconInformation)
        .build();
    let _ = dialog.show_modal();
}

pub(crate) fn is_affirmative_dialog_result(result: i32, affirmative_id: i32) -> bool {
    result == ID_OK || result == affirmative_id
}

pub(crate) fn is_dialog_accept_key(unicode_key: Option<i32>, key_code: Option<i32>) -> bool {
    matches!(
        unicode_key
            .and_then(|key| u32::try_from(key).ok())
            .and_then(char::from_u32),
        Some('\r' | '\n')
    ) || matches!(key_code, Some(10 | 13 | 370 | 372))
}

#[cfg(test)]
mod tests {
    use super::*;
    use wxdragon::id::{ID_CANCEL, ID_OK};

    #[test]
    fn affirmative_dialog_result_accepts_standard_ok() {
        assert!(is_affirmative_dialog_result(ID_OK, 12_345));
    }

    #[test]
    fn affirmative_dialog_result_accepts_custom_affirmative_id() {
        assert!(is_affirmative_dialog_result(12_345, 12_345));
    }

    #[test]
    fn affirmative_dialog_result_rejects_non_affirmative_values() {
        assert!(!is_affirmative_dialog_result(ID_CANCEL, 12_345));
        assert!(!is_affirmative_dialog_result(54_321, 12_345));
    }

    #[test]
    fn dialog_accept_key_accepts_enter_variants() {
        assert!(is_dialog_accept_key(Some('\r' as i32), None));
        assert!(is_dialog_accept_key(Some('\n' as i32), None));
        assert!(is_dialog_accept_key(None, Some(10)));
        assert!(is_dialog_accept_key(None, Some(13)));
        assert!(is_dialog_accept_key(None, Some(370)));
        assert!(is_dialog_accept_key(None, Some(372)));
        assert!(!is_dialog_accept_key(Some('a' as i32), Some(65)));
    }

    #[test]
    fn yes_no_confirmations_use_native_message_dialog() {
        let source = include_str!("dialog_support.rs")
            .split("#[cfg(test)]")
            .next()
            .expect("runtime source before tests");

        assert!(source.contains("MessageDialogStyle::YesNo"));
        assert!(source.contains("MessageDialogStyle::IconQuestion"));
        assert!(source.contains("dialog.show_modal() == ID_YES"));
        assert!(!source.contains("ConfirmationUi::new"));
        assert!(!source.contains("button_confirmation_yes"));
        assert!(!source.contains("button_confirmation_no"));
    }
}
