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

use crate::{AppInfoCreateFlags, AppLaunchContext, AsyncResult, Cancellable, File, Icon};
use glib::{prelude::*, translate::*};
use std::{boxed::Box as Box_, fmt, pin::Pin, ptr};

glib::wrapper! {
    #[doc(alias = "GAppInfo")]
    pub struct AppInfo(Interface<ffi::GAppInfo, ffi::GAppInfoIface>);

    match fn {
        type_ => || ffi::g_app_info_get_type(),
    }
}

impl AppInfo {
    pub const NONE: Option<&'static AppInfo> = None;

    #[doc(alias = "g_app_info_create_from_commandline")]
    pub fn create_from_commandline(
        commandline: impl AsRef<std::ffi::OsStr>,
        application_name: Option<&str>,
        flags: AppInfoCreateFlags,
    ) -> Result<AppInfo, glib::Error> {
        unsafe {
            let mut error = ptr::null_mut();
            let ret = ffi::g_app_info_create_from_commandline(
                commandline.as_ref().to_glib_none().0,
                application_name.to_glib_none().0,
                flags.into_glib(),
                &mut error,
            );
            if error.is_null() {
                Ok(from_glib_full(ret))
            } else {
                Err(from_glib_full(error))
            }
        }
    }

    #[doc(alias = "g_app_info_get_all")]
    #[doc(alias = "get_all")]
    pub fn all() -> Vec<AppInfo> {
        unsafe { FromGlibPtrContainer::from_glib_full(ffi::g_app_info_get_all()) }
    }

    #[doc(alias = "g_app_info_get_all_for_type")]
    #[doc(alias = "get_all_for_type")]
    pub fn all_for_type(content_type: &str) -> Vec<AppInfo> {
        unsafe {
            FromGlibPtrContainer::from_glib_full(ffi::g_app_info_get_all_for_type(
                content_type.to_glib_none().0,
            ))
        }
    }

    #[doc(alias = "g_app_info_get_default_for_type")]
    #[doc(alias = "get_default_for_type")]
    pub fn default_for_type(content_type: &str, must_support_uris: bool) -> Option<AppInfo> {
        unsafe {
            from_glib_full(ffi::g_app_info_get_default_for_type(
                content_type.to_glib_none().0,
                must_support_uris.into_glib(),
            ))
        }
    }

    #[cfg(feature = "v2_74")]
    #[cfg_attr(docsrs, doc(cfg(feature = "v2_74")))]
    #[doc(alias = "g_app_info_get_default_for_type_async")]
    #[doc(alias = "get_default_for_type_async")]
    pub fn default_for_type_async<P: FnOnce(Result<AppInfo, glib::Error>) + 'static>(
        content_type: &str,
        must_support_uris: bool,
        cancellable: Option<&impl IsA<Cancellable>>,
        callback: P,
    ) {
        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 default_for_type_async_trampoline<
            P: FnOnce(Result<AppInfo, glib::Error>) + 'static,
        >(
            _source_object: *mut glib::gobject_ffi::GObject,
            res: *mut crate::ffi::GAsyncResult,
            user_data: glib::ffi::gpointer,
        ) {
            let mut error = ptr::null_mut();
            let ret = ffi::g_app_info_get_default_for_type_finish(res, &mut error);
            let result = if error.is_null() {
                Ok(from_glib_full(ret))
            } 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 = default_for_type_async_trampoline::<P>;
        unsafe {
            ffi::g_app_info_get_default_for_type_async(
                content_type.to_glib_none().0,
                must_support_uris.into_glib(),
                cancellable.map(|p| p.as_ref()).to_glib_none().0,
                Some(callback),
                Box_::into_raw(user_data) as *mut _,
            );
        }
    }

    #[cfg(feature = "v2_74")]
    #[cfg_attr(docsrs, doc(cfg(feature = "v2_74")))]
    pub fn default_for_type_future(
        content_type: &str,
        must_support_uris: bool,
    ) -> Pin<Box_<dyn std::future::Future<Output = Result<AppInfo, glib::Error>> + 'static>> {
        let content_type = String::from(content_type);
        Box_::pin(crate::GioFuture::new(
            &(),
            move |_obj, cancellable, send| {
                Self::default_for_type_async(
                    &content_type,
                    must_support_uris,
                    Some(cancellable),
                    move |res| {
                        send.resolve(res);
                    },
                );
            },
        ))
    }

    #[doc(alias = "g_app_info_get_default_for_uri_scheme")]
    #[doc(alias = "get_default_for_uri_scheme")]
    pub fn default_for_uri_scheme(uri_scheme: &str) -> Option<AppInfo> {
        unsafe {
            from_glib_full(ffi::g_app_info_get_default_for_uri_scheme(
                uri_scheme.to_glib_none().0,
            ))
        }
    }

    #[cfg(feature = "v2_74")]
    #[cfg_attr(docsrs, doc(cfg(feature = "v2_74")))]
    #[doc(alias = "g_app_info_get_default_for_uri_scheme_async")]
    #[doc(alias = "get_default_for_uri_scheme_async")]
    pub fn default_for_uri_scheme_async<P: FnOnce(Result<AppInfo, glib::Error>) + 'static>(
        uri_scheme: &str,
        cancellable: Option<&impl IsA<Cancellable>>,
        callback: P,
    ) {
        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 default_for_uri_scheme_async_trampoline<
            P: FnOnce(Result<AppInfo, glib::Error>) + 'static,
        >(
            _source_object: *mut glib::gobject_ffi::GObject,
            res: *mut crate::ffi::GAsyncResult,
            user_data: glib::ffi::gpointer,
        ) {
            let mut error = ptr::null_mut();
            let ret = ffi::g_app_info_get_default_for_uri_scheme_finish(res, &mut error);
            let result = if error.is_null() {
                Ok(from_glib_full(ret))
            } 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 = default_for_uri_scheme_async_trampoline::<P>;
        unsafe {
            ffi::g_app_info_get_default_for_uri_scheme_async(
                uri_scheme.to_glib_none().0,
                cancellable.map(|p| p.as_ref()).to_glib_none().0,
                Some(callback),
                Box_::into_raw(user_data) as *mut _,
            );
        }
    }

    #[cfg(feature = "v2_74")]
    #[cfg_attr(docsrs, doc(cfg(feature = "v2_74")))]
    pub fn default_for_uri_scheme_future(
        uri_scheme: &str,
    ) -> Pin<Box_<dyn std::future::Future<Output = Result<AppInfo, glib::Error>> + 'static>> {
        let uri_scheme = String::from(uri_scheme);
        Box_::pin(crate::GioFuture::new(
            &(),
            move |_obj, cancellable, send| {
                Self::default_for_uri_scheme_async(&uri_scheme, Some(cancellable), move |res| {
                    send.resolve(res);
                });
            },
        ))
    }

    #[doc(alias = "g_app_info_get_fallback_for_type")]
    #[doc(alias = "get_fallback_for_type")]
    pub fn fallback_for_type(content_type: &str) -> Vec<AppInfo> {
        unsafe {
            FromGlibPtrContainer::from_glib_full(ffi::g_app_info_get_fallback_for_type(
                content_type.to_glib_none().0,
            ))
        }
    }

    #[doc(alias = "g_app_info_get_recommended_for_type")]
    #[doc(alias = "get_recommended_for_type")]
    pub fn recommended_for_type(content_type: &str) -> Vec<AppInfo> {
        unsafe {
            FromGlibPtrContainer::from_glib_full(ffi::g_app_info_get_recommended_for_type(
                content_type.to_glib_none().0,
            ))
        }
    }

    #[doc(alias = "g_app_info_launch_default_for_uri")]
    pub fn launch_default_for_uri(
        uri: &str,
        context: Option<&impl IsA<AppLaunchContext>>,
    ) -> Result<(), glib::Error> {
        unsafe {
            let mut error = ptr::null_mut();
            let is_ok = ffi::g_app_info_launch_default_for_uri(
                uri.to_glib_none().0,
                context.map(|p| p.as_ref()).to_glib_none().0,
                &mut error,
            );
            debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
            if error.is_null() {
                Ok(())
            } else {
                Err(from_glib_full(error))
            }
        }
    }

    #[doc(alias = "g_app_info_launch_default_for_uri_async")]
    pub fn launch_default_for_uri_async<P: FnOnce(Result<(), glib::Error>) + 'static>(
        uri: &str,
        context: Option<&impl IsA<AppLaunchContext>>,
        cancellable: Option<&impl IsA<Cancellable>>,
        callback: P,
    ) {
        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 launch_default_for_uri_async_trampoline<
            P: FnOnce(Result<(), glib::Error>) + 'static,
        >(
            _source_object: *mut glib::gobject_ffi::GObject,
            res: *mut crate::ffi::GAsyncResult,
            user_data: glib::ffi::gpointer,
        ) {
            let mut error = ptr::null_mut();
            let _ = ffi::g_app_info_launch_default_for_uri_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 = launch_default_for_uri_async_trampoline::<P>;
        unsafe {
            ffi::g_app_info_launch_default_for_uri_async(
                uri.to_glib_none().0,
                context.map(|p| p.as_ref()).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 launch_default_for_uri_future(
        uri: &str,
        context: Option<&(impl IsA<AppLaunchContext> + Clone + 'static)>,
    ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
        let uri = String::from(uri);
        let context = context.map(ToOwned::to_owned);
        Box_::pin(crate::GioFuture::new(
            &(),
            move |_obj, cancellable, send| {
                Self::launch_default_for_uri_async(
                    &uri,
                    context.as_ref().map(::std::borrow::Borrow::borrow),
                    Some(cancellable),
                    move |res| {
                        send.resolve(res);
                    },
                );
            },
        ))
    }

    #[doc(alias = "g_app_info_reset_type_associations")]
    pub fn reset_type_associations(content_type: &str) {
        unsafe {
            ffi::g_app_info_reset_type_associations(content_type.to_glib_none().0);
        }
    }
}

mod sealed {
    pub trait Sealed {}
    impl<T: super::IsA<super::AppInfo>> Sealed for T {}
}

pub trait AppInfoExt: IsA<AppInfo> + sealed::Sealed + 'static {
    #[doc(alias = "g_app_info_add_supports_type")]
    fn add_supports_type(&self, content_type: &str) -> Result<(), glib::Error> {
        unsafe {
            let mut error = ptr::null_mut();
            let is_ok = ffi::g_app_info_add_supports_type(
                self.as_ref().to_glib_none().0,
                content_type.to_glib_none().0,
                &mut error,
            );
            debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
            if error.is_null() {
                Ok(())
            } else {
                Err(from_glib_full(error))
            }
        }
    }

    #[doc(alias = "g_app_info_can_delete")]
    fn can_delete(&self) -> bool {
        unsafe { from_glib(ffi::g_app_info_can_delete(self.as_ref().to_glib_none().0)) }
    }

    #[doc(alias = "g_app_info_can_remove_supports_type")]
    fn can_remove_supports_type(&self) -> bool {
        unsafe {
            from_glib(ffi::g_app_info_can_remove_supports_type(
                self.as_ref().to_glib_none().0,
            ))
        }
    }

    #[doc(alias = "g_app_info_delete")]
    fn delete(&self) -> bool {
        unsafe { from_glib(ffi::g_app_info_delete(self.as_ref().to_glib_none().0)) }
    }

    #[doc(alias = "g_app_info_dup")]
    #[must_use]
    fn dup(&self) -> AppInfo {
        unsafe { from_glib_full(ffi::g_app_info_dup(self.as_ref().to_glib_none().0)) }
    }

    #[doc(alias = "g_app_info_equal")]
    fn equal(&self, appinfo2: &impl IsA<AppInfo>) -> bool {
        unsafe {
            from_glib(ffi::g_app_info_equal(
                self.as_ref().to_glib_none().0,
                appinfo2.as_ref().to_glib_none().0,
            ))
        }
    }

    #[doc(alias = "g_app_info_get_commandline")]
    #[doc(alias = "get_commandline")]
    fn commandline(&self) -> Option<std::path::PathBuf> {
        unsafe {
            from_glib_none(ffi::g_app_info_get_commandline(
                self.as_ref().to_glib_none().0,
            ))
        }
    }

    #[doc(alias = "g_app_info_get_description")]
    #[doc(alias = "get_description")]
    fn description(&self) -> Option<glib::GString> {
        unsafe {
            from_glib_none(ffi::g_app_info_get_description(
                self.as_ref().to_glib_none().0,
            ))
        }
    }

    #[doc(alias = "g_app_info_get_display_name")]
    #[doc(alias = "get_display_name")]
    fn display_name(&self) -> glib::GString {
        unsafe {
            from_glib_none(ffi::g_app_info_get_display_name(
                self.as_ref().to_glib_none().0,
            ))
        }
    }

    #[doc(alias = "g_app_info_get_executable")]
    #[doc(alias = "get_executable")]
    fn executable(&self) -> std::path::PathBuf {
        unsafe {
            from_glib_none(ffi::g_app_info_get_executable(
                self.as_ref().to_glib_none().0,
            ))
        }
    }

    #[doc(alias = "g_app_info_get_icon")]
    #[doc(alias = "get_icon")]
    fn icon(&self) -> Option<Icon> {
        unsafe { from_glib_none(ffi::g_app_info_get_icon(self.as_ref().to_glib_none().0)) }
    }

    #[doc(alias = "g_app_info_get_id")]
    #[doc(alias = "get_id")]
    fn id(&self) -> Option<glib::GString> {
        unsafe { from_glib_none(ffi::g_app_info_get_id(self.as_ref().to_glib_none().0)) }
    }

    #[doc(alias = "g_app_info_get_name")]
    #[doc(alias = "get_name")]
    fn name(&self) -> glib::GString {
        unsafe { from_glib_none(ffi::g_app_info_get_name(self.as_ref().to_glib_none().0)) }
    }

    #[doc(alias = "g_app_info_get_supported_types")]
    #[doc(alias = "get_supported_types")]
    fn supported_types(&self) -> Vec<glib::GString> {
        unsafe {
            FromGlibPtrContainer::from_glib_none(ffi::g_app_info_get_supported_types(
                self.as_ref().to_glib_none().0,
            ))
        }
    }

    #[doc(alias = "g_app_info_launch")]
    fn launch(
        &self,
        files: &[File],
        context: Option<&impl IsA<AppLaunchContext>>,
    ) -> Result<(), glib::Error> {
        unsafe {
            let mut error = ptr::null_mut();
            let is_ok = ffi::g_app_info_launch(
                self.as_ref().to_glib_none().0,
                files.to_glib_none().0,
                context.map(|p| p.as_ref()).to_glib_none().0,
                &mut error,
            );
            debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
            if error.is_null() {
                Ok(())
            } else {
                Err(from_glib_full(error))
            }
        }
    }

    #[doc(alias = "g_app_info_launch_uris")]
    fn launch_uris(
        &self,
        uris: &[&str],
        context: Option<&impl IsA<AppLaunchContext>>,
    ) -> Result<(), glib::Error> {
        unsafe {
            let mut error = ptr::null_mut();
            let is_ok = ffi::g_app_info_launch_uris(
                self.as_ref().to_glib_none().0,
                uris.to_glib_none().0,
                context.map(|p| p.as_ref()).to_glib_none().0,
                &mut error,
            );
            debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
            if error.is_null() {
                Ok(())
            } else {
                Err(from_glib_full(error))
            }
        }
    }

    #[doc(alias = "g_app_info_remove_supports_type")]
    fn remove_supports_type(&self, content_type: &str) -> Result<(), glib::Error> {
        unsafe {
            let mut error = ptr::null_mut();
            let is_ok = ffi::g_app_info_remove_supports_type(
                self.as_ref().to_glib_none().0,
                content_type.to_glib_none().0,
                &mut error,
            );
            debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
            if error.is_null() {
                Ok(())
            } else {
                Err(from_glib_full(error))
            }
        }
    }

    #[doc(alias = "g_app_info_set_as_default_for_extension")]
    fn set_as_default_for_extension(
        &self,
        extension: impl AsRef<std::path::Path>,
    ) -> Result<(), glib::Error> {
        unsafe {
            let mut error = ptr::null_mut();
            let is_ok = ffi::g_app_info_set_as_default_for_extension(
                self.as_ref().to_glib_none().0,
                extension.as_ref().to_glib_none().0,
                &mut error,
            );
            debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
            if error.is_null() {
                Ok(())
            } else {
                Err(from_glib_full(error))
            }
        }
    }

    #[doc(alias = "g_app_info_set_as_default_for_type")]
    fn set_as_default_for_type(&self, content_type: &str) -> Result<(), glib::Error> {
        unsafe {
            let mut error = ptr::null_mut();
            let is_ok = ffi::g_app_info_set_as_default_for_type(
                self.as_ref().to_glib_none().0,
                content_type.to_glib_none().0,
                &mut error,
            );
            debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
            if error.is_null() {
                Ok(())
            } else {
                Err(from_glib_full(error))
            }
        }
    }

    #[doc(alias = "g_app_info_set_as_last_used_for_type")]
    fn set_as_last_used_for_type(&self, content_type: &str) -> Result<(), glib::Error> {
        unsafe {
            let mut error = ptr::null_mut();
            let is_ok = ffi::g_app_info_set_as_last_used_for_type(
                self.as_ref().to_glib_none().0,
                content_type.to_glib_none().0,
                &mut error,
            );
            debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
            if error.is_null() {
                Ok(())
            } else {
                Err(from_glib_full(error))
            }
        }
    }

    #[doc(alias = "g_app_info_should_show")]
    fn should_show(&self) -> bool {
        unsafe { from_glib(ffi::g_app_info_should_show(self.as_ref().to_glib_none().0)) }
    }

    #[doc(alias = "g_app_info_supports_files")]
    fn supports_files(&self) -> bool {
        unsafe {
            from_glib(ffi::g_app_info_supports_files(
                self.as_ref().to_glib_none().0,
            ))
        }
    }

    #[doc(alias = "g_app_info_supports_uris")]
    fn supports_uris(&self) -> bool {
        unsafe {
            from_glib(ffi::g_app_info_supports_uris(
                self.as_ref().to_glib_none().0,
            ))
        }
    }
}

impl<O: IsA<AppInfo>> AppInfoExt for O {}

impl fmt::Display for AppInfo {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("AppInfo")
    }
}
