//! This file has been automatically generated by `objc2`'s `header-translator`.
//! DO NOT EDIT
use core::ffi::*;
use core::ptr::NonNull;
use objc2::__framework_prelude::*;
use objc2_foundation::*;

use crate::*;

/// [Apple's documentation](https://developer.apple.com/documentation/uikit/uitabbarcontrollersidebarlayout?language=objc)
// NS_ENUM
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct UITabBarControllerSidebarLayout(pub NSInteger);
impl UITabBarControllerSidebarLayout {
    /// On iOS, this resolves to `overlap`.
    /// On macOS and visionOS, this resolves to `tile`.
    #[doc(alias = "UITabBarControllerSidebarLayoutAutomatic")]
    pub const Automatic: Self = Self(0);
    /// When the sidebar is displayed, it will overlap the selected view controller,
    /// allowing the selected view controller to render underneath the sidebar. Anchor
    /// the view's content to the `layoutMarginsGuide` or `safeAreaLayoutGuide` to avoid
    /// being occluded by the sidebar.
    #[doc(alias = "UITabBarControllerSidebarLayoutOverlap")]
    pub const Overlap: Self = Self(1);
    /// When the sidebar is displayed, the selected view controller is resized and shifted
    /// to display alongside the sidebar. The selected view controller is not occluded by
    /// the sidebar, cannot render underneath the sidebar.
    #[doc(alias = "UITabBarControllerSidebarLayoutTile")]
    pub const Tile: Self = Self(2);
}

unsafe impl Encode for UITabBarControllerSidebarLayout {
    const ENCODING: Encoding = NSInteger::ENCODING;
}

unsafe impl RefEncode for UITabBarControllerSidebarLayout {
    const ENCODING_REF: Encoding = Encoding::Pointer(&Self::ENCODING);
}

extern_class!(
    /// [Apple's documentation](https://developer.apple.com/documentation/uikit/uitabsidebarscrolltarget?language=objc)
    #[unsafe(super(NSObject))]
    #[thread_kind = MainThreadOnly]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct UITabSidebarScrollTarget;
);

extern_conformance!(
    unsafe impl NSObjectProtocol for UITabSidebarScrollTarget {}
);

impl UITabSidebarScrollTarget {
    extern_methods!(
        /// Scrolls to the `headerContentConfiguration` if it is set.
        #[unsafe(method(targetForHeader))]
        #[unsafe(method_family = none)]
        pub fn targetForHeader(mtm: MainThreadMarker) -> Retained<Self>;

        /// Scrolls to the `footerContentConfiguration` if it is set.
        #[unsafe(method(targetForFooter))]
        #[unsafe(method_family = none)]
        pub fn targetForFooter(mtm: MainThreadMarker) -> Retained<Self>;

        #[cfg(feature = "UITab")]
        /// Scrolls to the item representing the tab if it exists.
        #[unsafe(method(targetForTab:))]
        #[unsafe(method_family = none)]
        pub fn targetForTab(tab: &UITab) -> Retained<Self>;
    );
}

/// Methods declared on superclass `NSObject`.
impl UITabSidebarScrollTarget {
    extern_methods!(
        #[unsafe(method(init))]
        #[unsafe(method_family = init)]
        pub fn init(this: Allocated<Self>) -> Retained<Self>;

        #[unsafe(method(new))]
        #[unsafe(method_family = new)]
        pub fn new(mtm: MainThreadMarker) -> Retained<Self>;
    );
}

extern_class!(
    /// [Apple's documentation](https://developer.apple.com/documentation/uikit/uitabbarcontrollersidebar?language=objc)
    #[unsafe(super(NSObject))]
    #[thread_kind = MainThreadOnly]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct UITabBarControllerSidebar;
);

extern_conformance!(
    unsafe impl NSObjectProtocol for UITabBarControllerSidebar {}
);

impl UITabBarControllerSidebar {
    extern_methods!(
        /// The object managing the delegate of the sidebar.
        #[unsafe(method(delegate))]
        #[unsafe(method_family = none)]
        pub fn delegate(
            &self,
        ) -> Option<Retained<ProtocolObject<dyn UITabBarControllerSidebarDelegate>>>;

        /// Setter for [`delegate`][Self::delegate].
        ///
        /// This is a [weak property][objc2::topics::weak_property].
        #[unsafe(method(setDelegate:))]
        #[unsafe(method_family = none)]
        pub fn setDelegate(
            &self,
            delegate: Option<&ProtocolObject<dyn UITabBarControllerSidebarDelegate>>,
        );

        /// Determines if the sidebar is currently hidden.
        #[unsafe(method(isHidden))]
        #[unsafe(method_family = none)]
        pub fn isHidden(&self) -> bool;

        /// Setter for [`isHidden`][Self::isHidden].
        #[unsafe(method(setHidden:))]
        #[unsafe(method_family = none)]
        pub fn setHidden(&self, hidden: bool);

        /// The preferred layout for how the sidebar lays out with the tab bar controller's
        /// content. Default is `.automatic`
        #[unsafe(method(preferredLayout))]
        #[unsafe(method_family = none)]
        pub fn preferredLayout(&self) -> UITabBarControllerSidebarLayout;

        /// Setter for [`preferredLayout`][Self::preferredLayout].
        #[unsafe(method(setPreferredLayout:))]
        #[unsafe(method_family = none)]
        pub fn setPreferredLayout(&self, preferred_layout: UITabBarControllerSidebarLayout);

        #[cfg(all(feature = "UIDeferredMenuElement", feature = "UIMenuElement"))]
        /// Additional items to add to the overflow menu in the sidebar's navigation bar. Setting this property to a non-nil value will force the overflow button
        /// to appear, regardless of if you provide any content in the element's callback. Items returned are displayed directly in the presented menu. When
        /// set, the "Edit Sidebar" action will also be moved into the overflow menu after the app-provided items.
        #[unsafe(method(navigationOverflowItems))]
        #[unsafe(method_family = none)]
        pub fn navigationOverflowItems(&self) -> Option<Retained<UIDeferredMenuElement>>;

        #[cfg(all(feature = "UIDeferredMenuElement", feature = "UIMenuElement"))]
        /// Setter for [`navigationOverflowItems`][Self::navigationOverflowItems].
        #[unsafe(method(setNavigationOverflowItems:))]
        #[unsafe(method_family = none)]
        pub fn setNavigationOverflowItems(
            &self,
            navigation_overflow_items: Option<&UIDeferredMenuElement>,
        );

        #[cfg(feature = "UIContentConfiguration")]
        /// Content configuration for an optional header to display in the sidebar.
        /// The header is displayed above all tab content in the sidebar.
        #[unsafe(method(headerContentConfiguration))]
        #[unsafe(method_family = none)]
        pub fn headerContentConfiguration(
            &self,
        ) -> Option<Retained<ProtocolObject<dyn UIContentConfiguration>>>;

        #[cfg(feature = "UIContentConfiguration")]
        /// Setter for [`headerContentConfiguration`][Self::headerContentConfiguration].
        ///
        /// This is [copied][objc2_foundation::NSCopying::copy] when set.
        #[unsafe(method(setHeaderContentConfiguration:))]
        #[unsafe(method_family = none)]
        pub fn setHeaderContentConfiguration(
            &self,
            header_content_configuration: Option<&ProtocolObject<dyn UIContentConfiguration>>,
        );

        #[cfg(feature = "UIContentConfiguration")]
        /// Content configuration for an optional header to display in the sidebar.
        /// The footer is displayed below all tab content in the sidebar.
        #[unsafe(method(footerContentConfiguration))]
        #[unsafe(method_family = none)]
        pub fn footerContentConfiguration(
            &self,
        ) -> Option<Retained<ProtocolObject<dyn UIContentConfiguration>>>;

        #[cfg(feature = "UIContentConfiguration")]
        /// Setter for [`footerContentConfiguration`][Self::footerContentConfiguration].
        ///
        /// This is [copied][objc2_foundation::NSCopying::copy] when set.
        #[unsafe(method(setFooterContentConfiguration:))]
        #[unsafe(method_family = none)]
        pub fn setFooterContentConfiguration(
            &self,
            footer_content_configuration: Option<&ProtocolObject<dyn UIContentConfiguration>>,
        );

        #[cfg(all(feature = "UIResponder", feature = "UIView"))]
        /// A view to display at the bottom of the sidebar, like a UIToolbar. The width of this view
        /// will be managed by the sidebar itself, and its height will be set to the value it returns
        /// from `systemLayoutSizeFittingSize:withHorizontalFittingPriority:verticalFittingPriority:`
        /// Default is nil.
        #[unsafe(method(bottomBarView))]
        #[unsafe(method_family = none)]
        pub fn bottomBarView(&self) -> Option<Retained<UIView>>;

        #[cfg(all(feature = "UIResponder", feature = "UIView"))]
        /// Setter for [`bottomBarView`][Self::bottomBarView].
        #[unsafe(method(setBottomBarView:))]
        #[unsafe(method_family = none)]
        pub fn setBottomBarView(&self, bottom_bar_view: Option<&UIView>);

        /// Scrolls to the specified target in the sidebar with an option to animate the change.
        #[unsafe(method(scrollToTarget:animated:))]
        #[unsafe(method_family = none)]
        pub fn scrollToTarget_animated(&self, target: &UITabSidebarScrollTarget, animated: bool);

        #[cfg(feature = "UITab")]
        /// Requests the sidebar reconfigure the item representing the specified tab. This method has no effect if the `tab` is not
        /// currently displayed in the sidebar.
        #[unsafe(method(reconfigureItemForTab:))]
        #[unsafe(method_family = none)]
        pub fn reconfigureItemForTab(&self, tab: &UITab);

        #[unsafe(method(init))]
        #[unsafe(method_family = init)]
        pub unsafe fn init(this: Allocated<Self>) -> Retained<Self>;

        #[unsafe(method(new))]
        #[unsafe(method_family = new)]
        pub unsafe fn new(mtm: MainThreadMarker) -> Retained<Self>;
    );
}

extern_protocol!(
    /// [Apple's documentation](https://developer.apple.com/documentation/uikit/uitabbarcontrollersidebaranimating?language=objc)
    pub unsafe trait UITabBarControllerSidebarAnimating:
        NSObjectProtocol + MainThreadOnly
    {
        #[cfg(feature = "block2")]
        #[unsafe(method(addAnimations:))]
        #[unsafe(method_family = none)]
        fn addAnimations(&self, animations: &block2::DynBlock<dyn Fn()>);

        #[cfg(feature = "block2")]
        #[unsafe(method(addCompletion:))]
        #[unsafe(method_family = none)]
        fn addCompletion(&self, completion: &block2::DynBlock<dyn Fn()>);
    }
);

extern_protocol!(
    /// [Apple's documentation](https://developer.apple.com/documentation/uikit/uitabbarcontrollersidebardelegate?language=objc)
    pub unsafe trait UITabBarControllerSidebarDelegate:
        NSObjectProtocol + MainThreadOnly
    {
        #[cfg(all(
            feature = "UIResponder",
            feature = "UITabBarController",
            feature = "UIViewController"
        ))]
        /// Notifies the delegate when the visibility of the sidebar is about to change when `sidebar.isHidden` changes.
        /// Add animations to the animator to run alongside the visibility update. Alongside animations and completions will run immediately
        /// if the sidebar visibility is changed without animation.
        #[optional]
        #[unsafe(method(tabBarController:sidebarVisibilityWillChange:animator:))]
        #[unsafe(method_family = none)]
        fn tabBarController_sidebarVisibilityWillChange_animator(
            &self,
            tab_bar_controller: &UITabBarController,
            sidebar: &UITabBarControllerSidebar,
            animator: &ProtocolObject<dyn UITabBarControllerSidebarAnimating>,
        );

        #[cfg(all(
            feature = "UIResponder",
            feature = "UITabBarController",
            feature = "UITabSidebarItem",
            feature = "UIViewController"
        ))]
        /// Return a `UITabSidebarItem` for the specified item request. When created, the item will be preconfigured
        /// to the appropriate defaults for its given content. If this method is not implemented, a default sidebar
        /// item will be provided for the request.
        #[optional]
        #[unsafe(method(tabBarController:sidebar:itemForRequest:))]
        #[unsafe(method_family = none)]
        fn tabBarController_sidebar_itemForRequest(
            &self,
            tab_bar_controller: &UITabBarController,
            sidebar: &UITabBarControllerSidebar,
            request: &UITabSidebarItemRequest,
        ) -> Retained<UITabSidebarItem>;

        #[cfg(all(
            feature = "UIResponder",
            feature = "UITabBarController",
            feature = "UITabSidebarItem",
            feature = "UIViewController"
        ))]
        /// Called whenever the sidebar item's `configurationState` changes or the item is reconfigured.
        /// The passed in item will accrue all modifications until the delegate requests for a new sidebar
        /// item from the delegate method `tabBarController:sidebar:itemForRequest:`
        #[optional]
        #[unsafe(method(tabBarController:sidebar:updateItem:))]
        #[unsafe(method_family = none)]
        fn tabBarController_sidebar_updateItem(
            &self,
            tab_bar_controller: &UITabBarController,
            sidebar: &UITabBarControllerSidebar,
            item: &UITabSidebarItem,
        );

        #[cfg(all(
            feature = "UIResponder",
            feature = "UITab",
            feature = "UITabBarController",
            feature = "UIViewController"
        ))]
        /// Notifies the delegate when the sidebar is about to display the row representing the specified `tab`
        #[optional]
        #[unsafe(method(tabBarController:sidebar:willBeginDisplayingTab:))]
        #[unsafe(method_family = none)]
        fn tabBarController_sidebar_willBeginDisplayingTab(
            &self,
            tab_bar_controller: &UITabBarController,
            sidebar: &UITabBarControllerSidebar,
            tab: &UITab,
        );

        #[cfg(all(
            feature = "UIResponder",
            feature = "UITab",
            feature = "UITabBarController",
            feature = "UIViewController"
        ))]
        /// Notifies the delegate when the sidebar has finished displaying the row representing the specified `tab`
        #[optional]
        #[unsafe(method(tabBarController:sidebar:didEndDisplayingTab:))]
        #[unsafe(method_family = none)]
        fn tabBarController_sidebar_didEndDisplayingTab(
            &self,
            tab_bar_controller: &UITabBarController,
            sidebar: &UITabBarControllerSidebar,
            tab: &UITab,
        );

        #[cfg(all(
            feature = "UIResponder",
            feature = "UISwipeActionsConfiguration",
            feature = "UITab",
            feature = "UITabBarController",
            feature = "UIViewController"
        ))]
        /// Called when the sidebar is about to show leading swipe actions for the specified `tab`.
        /// Return either a concrete `UISwipeActionsConfiguration` or nil if the tab does not show swipe actions.
        #[optional]
        #[unsafe(method(tabBarController:sidebar:leadingSwipeActionsConfigurationForTab:))]
        #[unsafe(method_family = none)]
        fn tabBarController_sidebar_leadingSwipeActionsConfigurationForTab(
            &self,
            tab_bar_controller: &UITabBarController,
            sidebar: &UITabBarControllerSidebar,
            tab: &UITab,
        ) -> Option<Retained<UISwipeActionsConfiguration>>;

        #[cfg(all(
            feature = "UIResponder",
            feature = "UISwipeActionsConfiguration",
            feature = "UITab",
            feature = "UITabBarController",
            feature = "UIViewController"
        ))]
        /// Called when the sidebar is about to show trailing swipe actions for a particular tab.
        /// Return either a UISwipeActionsConfiguration object or nil if this tab does not show swipe actions.
        #[optional]
        #[unsafe(method(tabBarController:sidebar:trailingSwipeActionsConfigurationForTab:))]
        #[unsafe(method_family = none)]
        fn tabBarController_sidebar_trailingSwipeActionsConfigurationForTab(
            &self,
            tab_bar_controller: &UITabBarController,
            sidebar: &UITabBarControllerSidebar,
            tab: &UITab,
        ) -> Option<Retained<UISwipeActionsConfiguration>>;

        #[cfg(all(
            feature = "UIContextMenuConfiguration",
            feature = "UIResponder",
            feature = "UITab",
            feature = "UITabBarController",
            feature = "UIViewController"
        ))]
        /// Called when the sidebar is about to display a context menu for the specified `tab`.
        /// Return either a concrete `UIContextMenuConfiguration` or nil if the tab does not show context menus.
        #[optional]
        #[unsafe(method(tabBarController:sidebar:contextMenuConfigurationForTab:))]
        #[unsafe(method_family = none)]
        fn tabBarController_sidebar_contextMenuConfigurationForTab(
            &self,
            tab_bar_controller: &UITabBarController,
            sidebar: &UITabBarControllerSidebar,
            tab: &UITab,
        ) -> Option<Retained<UIContextMenuConfiguration>>;

        #[cfg(all(
            feature = "UIDragItem",
            feature = "UIDragSession",
            feature = "UIResponder",
            feature = "UITab",
            feature = "UITabBarController",
            feature = "UIViewController"
        ))]
        /// Called when a new drag session has begun in the sidebar from the specified `tab`. Return drag items if the specified tab can be dragged, or an empty array if no drags should begin.
        /// Note that if drag items are returned on tabs in groups that allow reordering, then tab reordering is disabled when the sidebar is not in editing.
        #[optional]
        #[unsafe(method(tabBarController:sidebar:itemsForBeginningDragSession:tab:))]
        #[unsafe(method_family = none)]
        fn tabBarController_sidebar_itemsForBeginningDragSession_tab(
            &self,
            tab_bar_controller: &UITabBarController,
            sidebar: &UITabBarControllerSidebar,
            drag_session: &ProtocolObject<dyn UIDragSession>,
            tab: &UITab,
        ) -> Retained<NSArray<UIDragItem>>;

        #[cfg(all(
            feature = "UIDragItem",
            feature = "UIDragSession",
            feature = "UIResponder",
            feature = "UITab",
            feature = "UITabBarController",
            feature = "UIViewController"
        ))]
        /// Called when a new drag session is requesting items to add to the existing drag session in the sidebar from the specified `tab`.
        /// Return items if the specified tab can add to the drag session, or an empty array if nothing should be added.
        #[optional]
        #[unsafe(method(tabBarController:sidebar:itemsForAddingToDragSession:tab:))]
        #[unsafe(method_family = none)]
        fn tabBarController_sidebar_itemsForAddingToDragSession_tab(
            &self,
            tab_bar_controller: &UITabBarController,
            sidebar: &UITabBarControllerSidebar,
            drag_session: &ProtocolObject<dyn UIDragSession>,
            tab: &UITab,
        ) -> Retained<NSArray<UIDragItem>>;

        #[cfg(all(
            feature = "UIAction",
            feature = "UIDragSession",
            feature = "UIDropInteraction",
            feature = "UIMenuElement",
            feature = "UIResponder",
            feature = "UITab",
            feature = "UITabBarController",
            feature = "UITabGroup",
            feature = "UIViewController"
        ))]
        /// Determines if items from the specified drop session can be dropped into the specified `sidebarAction`. If the operation is either a `.move` or `.copy`,
        /// then the drop will proceed and `tabBarController:sidebar:sidebarAction:acceptItemsFromDropSession:` is called. By default, the drop will be
        /// treated as a cancel operation if this is not implemented.
        #[optional]
        #[unsafe(method(tabBarController:sidebar:sidebarAction:group:operationForAcceptingItemsFromDropSession:))]
        #[unsafe(method_family = none)]
        fn tabBarController_sidebar_sidebarAction_group_operationForAcceptingItemsFromDropSession(
            &self,
            tab_bar_controller: &UITabBarController,
            sidebar: &UITabBarControllerSidebar,
            sidebar_action: &UIAction,
            group: &UITabGroup,
            session: &ProtocolObject<dyn UIDropSession>,
        ) -> UIDropOperation;

        #[cfg(all(
            feature = "UIAction",
            feature = "UIDragSession",
            feature = "UIMenuElement",
            feature = "UIResponder",
            feature = "UITab",
            feature = "UITabBarController",
            feature = "UITabGroup",
            feature = "UIViewController"
        ))]
        /// Receive the drop from into the `sidebarAction` using the specified session. This is only called if the drop operation returned
        /// from `tabBarController:sidebar:sidebarAction:operationForAcceptingItemsFromDropSession` is valid for a drop.
        #[optional]
        #[unsafe(method(tabBarController:sidebar:sidebarAction:group:acceptItemsFromDropSession:))]
        #[unsafe(method_family = none)]
        fn tabBarController_sidebar_sidebarAction_group_acceptItemsFromDropSession(
            &self,
            tab_bar_controller: &UITabBarController,
            sidebar: &UITabBarControllerSidebar,
            sidebar_action: &UIAction,
            group: &UITabGroup,
            session: &ProtocolObject<dyn UIDropSession>,
        );
    }
);
