// This file was generated by gir (https://github.com/gtk-rs/gir)
// from gir-files (https://github.com/gtk-rs/gir-files.git)
// DO NOT EDIT

use crate::DesktopThumbnailSize;
use glib::{prelude::*, translate::*};
use std::{boxed::Box as Box_, pin::Pin, ptr};

#[doc(alias = "gnome_desktop_thumbnail_is_valid")]
pub fn desktop_thumbnail_is_valid(
    pixbuf: &gdk_pixbuf::Pixbuf,
    uri: &str,
    mtime: libc::c_long,
) -> bool {
    assert_initialized_main_thread!();
    unsafe {
        from_glib(ffi::gnome_desktop_thumbnail_is_valid(
            pixbuf.to_glib_none().0,
            uri.to_glib_none().0,
            mtime,
        ))
    }
}

#[doc(alias = "gnome_desktop_thumbnail_path_for_uri")]
pub fn desktop_thumbnail_path_for_uri(
    uri: &str,
    size: DesktopThumbnailSize,
) -> Option<glib::GString> {
    assert_initialized_main_thread!();
    unsafe {
        from_glib_full(ffi::gnome_desktop_thumbnail_path_for_uri(
            uri.to_glib_none().0,
            size.into_glib(),
        ))
    }
}

#[doc(alias = "gnome_get_all_locales")]
#[doc(alias = "get_all_locales")]
pub fn all_locales() -> Vec<glib::GString> {
    assert_initialized_main_thread!();
    unsafe { FromGlibPtrContainer::from_glib_full(ffi::gnome_get_all_locales()) }
}

#[doc(alias = "gnome_get_country_from_code")]
#[doc(alias = "get_country_from_code")]
pub fn country_from_code(code: &str, translation: Option<&str>) -> Option<glib::GString> {
    assert_initialized_main_thread!();
    unsafe {
        from_glib_full(ffi::gnome_get_country_from_code(
            code.to_glib_none().0,
            translation.to_glib_none().0,
        ))
    }
}

#[doc(alias = "gnome_get_country_from_locale")]
#[doc(alias = "get_country_from_locale")]
pub fn country_from_locale(locale: &str, translation: Option<&str>) -> Option<glib::GString> {
    assert_initialized_main_thread!();
    unsafe {
        from_glib_full(ffi::gnome_get_country_from_locale(
            locale.to_glib_none().0,
            translation.to_glib_none().0,
        ))
    }
}

#[doc(alias = "gnome_get_input_source_from_locale")]
#[doc(alias = "get_input_source_from_locale")]
pub fn input_source_from_locale(locale: &str) -> Option<(glib::GString, glib::GString)> {
    assert_initialized_main_thread!();
    unsafe {
        let mut type_ = ptr::null();
        let mut id = ptr::null();
        let ret = from_glib(ffi::gnome_get_input_source_from_locale(
            locale.to_glib_none().0,
            &mut type_,
            &mut id,
        ));
        if ret {
            Some((from_glib_none(type_), from_glib_none(id)))
        } else {
            None
        }
    }
}

#[doc(alias = "gnome_get_language_from_code")]
#[doc(alias = "get_language_from_code")]
pub fn language_from_code(code: &str, translation: Option<&str>) -> Option<glib::GString> {
    assert_initialized_main_thread!();
    unsafe {
        from_glib_full(ffi::gnome_get_language_from_code(
            code.to_glib_none().0,
            translation.to_glib_none().0,
        ))
    }
}

#[doc(alias = "gnome_get_language_from_locale")]
#[doc(alias = "get_language_from_locale")]
pub fn language_from_locale(locale: &str, translation: Option<&str>) -> Option<glib::GString> {
    assert_initialized_main_thread!();
    unsafe {
        from_glib_full(ffi::gnome_get_language_from_locale(
            locale.to_glib_none().0,
            translation.to_glib_none().0,
        ))
    }
}

#[cfg(feature = "v43")]
#[cfg_attr(docsrs, doc(cfg(feature = "v43")))]
#[doc(alias = "gnome_get_platform_version")]
#[doc(alias = "get_platform_version")]
pub fn platform_version() -> i32 {
    assert_initialized_main_thread!();
    unsafe { ffi::gnome_get_platform_version() }
}

#[doc(alias = "gnome_get_translated_modifier")]
#[doc(alias = "get_translated_modifier")]
pub fn translated_modifier(modifier: &str, translation: Option<&str>) -> Option<glib::GString> {
    assert_initialized_main_thread!();
    unsafe {
        from_glib_full(ffi::gnome_get_translated_modifier(
            modifier.to_glib_none().0,
            translation.to_glib_none().0,
        ))
    }
}

#[doc(alias = "gnome_language_has_translations")]
pub fn language_has_translations(code: &str) -> bool {
    assert_initialized_main_thread!();
    unsafe { from_glib(ffi::gnome_language_has_translations(code.to_glib_none().0)) }
}

#[doc(alias = "gnome_normalize_locale")]
pub fn normalize_locale(locale: &str) -> Option<glib::GString> {
    assert_initialized_main_thread!();
    unsafe { from_glib_full(ffi::gnome_normalize_locale(locale.to_glib_none().0)) }
}

#[doc(alias = "gnome_parse_locale")]
pub fn parse_locale(
    locale: &str,
) -> Option<(
    glib::GString,
    Option<glib::GString>,
    Option<glib::GString>,
    Option<glib::GString>,
)> {
    assert_initialized_main_thread!();
    unsafe {
        let mut language_codep = ptr::null_mut();
        let mut country_codep = ptr::null_mut();
        let mut codesetp = ptr::null_mut();
        let mut modifierp = ptr::null_mut();
        let ret = from_glib(ffi::gnome_parse_locale(
            locale.to_glib_none().0,
            &mut language_codep,
            &mut country_codep,
            &mut codesetp,
            &mut modifierp,
        ));
        if ret {
            Some((
                from_glib_full(language_codep),
                from_glib_full(country_codep),
                from_glib_full(codesetp),
                from_glib_full(modifierp),
            ))
        } else {
            None
        }
    }
}

#[doc(alias = "gnome_start_systemd_scope")]
pub fn start_systemd_scope<P: FnOnce(Result<(), glib::Error>) + 'static>(
    name: &str,
    pid: i32,
    description: Option<&str>,
    connection: Option<&gio::DBusConnection>,
    cancellable: Option<&impl IsA<gio::Cancellable>>,
    callback: P,
) {
    assert_initialized_main_thread!();

    let main_context = glib::MainContext::ref_thread_default();
    let is_main_context_owner = main_context.is_owner();
    let has_acquired_main_context = (!is_main_context_owner)
        .then(|| main_context.acquire().ok())
        .flatten();
    assert!(
        is_main_context_owner || has_acquired_main_context.is_some(),
        "Async operations only allowed if the thread is owning the MainContext"
    );

    let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
        Box_::new(glib::thread_guard::ThreadGuard::new(callback));
    unsafe extern "C" fn start_systemd_scope_trampoline<
        P: FnOnce(Result<(), glib::Error>) + 'static,
    >(
        _source_object: *mut glib::gobject_ffi::GObject,
        res: *mut gio::ffi::GAsyncResult,
        user_data: glib::ffi::gpointer,
    ) {
        let mut error = ptr::null_mut();
        let _ = ffi::gnome_start_systemd_scope_finish(res, &mut error);
        let result = if error.is_null() {
            Ok(())
        } else {
            Err(from_glib_full(error))
        };
        let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
            Box_::from_raw(user_data as *mut _);
        let callback: P = callback.into_inner();
        callback(result);
    }
    let callback = start_systemd_scope_trampoline::<P>;
    unsafe {
        ffi::gnome_start_systemd_scope(
            name.to_glib_none().0,
            pid,
            description.to_glib_none().0,
            connection.to_glib_none().0,
            cancellable.map(|p| p.as_ref()).to_glib_none().0,
            Some(callback),
            Box_::into_raw(user_data) as *mut _,
        );
    }
}

pub fn start_systemd_scope_future(
    name: &str,
    pid: i32,
    description: Option<&str>,
    connection: Option<&gio::DBusConnection>,
) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
    skip_assert_initialized!();
    let name = String::from(name);
    let description = description.map(ToOwned::to_owned);
    let connection = connection.map(ToOwned::to_owned);
    Box_::pin(gio::GioFuture::new(&(), move |_obj, cancellable, send| {
        start_systemd_scope(
            &name,
            pid,
            description.as_ref().map(::std::borrow::Borrow::borrow),
            connection.as_ref().map(::std::borrow::Borrow::borrow),
            Some(cancellable),
            move |res| {
                send.resolve(res);
            },
        );
    }))
}
