//! 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::*;
#[cfg(feature = "objc2-core-foundation")]
use objc2_core_foundation::*;
use objc2_foundation::*;

use crate::*;

/// [Apple's documentation](https://developer.apple.com/documentation/uikit/uifocusheading?language=objc)
// NS_OPTIONS
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct UIFocusHeading(pub NSUInteger);
bitflags::bitflags! {
    impl UIFocusHeading: NSUInteger {
        #[doc(alias = "UIFocusHeadingNone")]
        const None = 0;
        #[doc(alias = "UIFocusHeadingUp")]
        const Up = 1<<0;
        #[doc(alias = "UIFocusHeadingDown")]
        const Down = 1<<1;
        #[doc(alias = "UIFocusHeadingLeft")]
        const Left = 1<<2;
        #[doc(alias = "UIFocusHeadingRight")]
        const Right = 1<<3;
        #[doc(alias = "UIFocusHeadingNext")]
        const Next = 1<<4;
        #[doc(alias = "UIFocusHeadingPrevious")]
        const Previous = 1<<5;
        #[doc(alias = "UIFocusHeadingFirst")]
        const First = 1<<8;
        #[doc(alias = "UIFocusHeadingLast")]
        const Last = 1<<9;
    }
}

unsafe impl Encode for UIFocusHeading {
    const ENCODING: Encoding = NSUInteger::ENCODING;
}

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

/// [Apple's documentation](https://developer.apple.com/documentation/uikit/uifocusitemdeferralmode?language=objc)
// NS_ENUM
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct UIFocusItemDeferralMode(pub NSInteger);
impl UIFocusItemDeferralMode {
    /// Use the system default behavior.
    #[doc(alias = "UIFocusItemDeferralModeAutomatic")]
    pub const Automatic: Self = Self(0);
    /// Always defer focus for this item, even if deferral is disabled right now.
    /// This means a programmatic update to this item would result in focus
    /// disappearing until the user interacts with the focus engine again.
    #[doc(alias = "UIFocusItemDeferralModeAlways")]
    pub const Always: Self = Self(1);
    /// Never defer focus for this item. When a programmatic focus update
    /// lands on this item, it will always be and appear focused even if focus
    /// deferral is currently enabled.
    #[doc(alias = "UIFocusItemDeferralModeNever")]
    pub const Never: Self = Self(2);
}

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

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

/// [Apple's documentation](https://developer.apple.com/documentation/uikit/uifocussoundidentifier?language=objc)
// NS_TYPED_EXTENSIBLE_ENUM
pub type UIFocusSoundIdentifier = NSString;

/// These are focus group priorities that the system uses and that clients can use to make an item
/// more or less important than these system states. Any priority below 0 will be ignored.
///
/// See also [Apple's documentation](https://developer.apple.com/documentation/uikit/uifocusgrouppriority?language=objc)
// NS_TYPED_EXTENSIBLE_ENUM
pub type UIFocusGroupPriority = NSInteger;

/// [Apple's documentation](https://developer.apple.com/documentation/uikit/uifocusgrouppriorityignored?language=objc)
pub static UIFocusGroupPriorityIgnored: UIFocusGroupPriority = 0;

/// [Apple's documentation](https://developer.apple.com/documentation/uikit/uifocusgroupprioritypreviouslyfocused?language=objc)
pub static UIFocusGroupPriorityPreviouslyFocused: UIFocusGroupPriority = 1000;

/// [Apple's documentation](https://developer.apple.com/documentation/uikit/uifocusgrouppriorityprioritized?language=objc)
pub static UIFocusGroupPriorityPrioritized: UIFocusGroupPriority = 2000;

/// [Apple's documentation](https://developer.apple.com/documentation/uikit/uifocusgroupprioritycurrentlyfocused?language=objc)
pub static UIFocusGroupPriorityCurrentlyFocused: UIFocusGroupPriority = NSIntegerMax as _;

extern_protocol!(
    /// Objects conforming to UIFocusEnvironment influence and respond to focus behavior within a specific area of the screen that they control.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/uikit/uifocusenvironment?language=objc)
    pub unsafe trait UIFocusEnvironment: NSObjectProtocol + MainThreadOnly {
        /// The preferred focus environments define where to search for the default focused item in an environment, such as when focus updates programmatically.
        /// Starting from the target environment, each preferred focus environment is recursively searched in the order of the array until an eligible, focusable item is found.
        /// Preferred focus environments can include focusable and non-focusable items, in addition to non-item environments. Returning an empty array is equivalent to returning an array containing only 'self'.
        #[unsafe(method(preferredFocusEnvironments))]
        #[unsafe(method_family = none)]
        fn preferredFocusEnvironments(
            &self,
        ) -> Retained<NSArray<ProtocolObject<dyn UIFocusEnvironment>>>;

        /// The parent focus environment of this environment, or nil if no parent exists.
        /// NOTE: If you implement this method, you must return a non-nil value for parent focus environment, otherwise your focus environment will not participate in focus interactions.
        #[unsafe(method(parentFocusEnvironment))]
        #[unsafe(method_family = none)]
        fn parentFocusEnvironment(
            &self,
        ) -> Option<Retained<ProtocolObject<dyn UIFocusEnvironment>>>;

        /// The container of any child focus items in this focus environment, or nil if no container exists.
        #[unsafe(method(focusItemContainer))]
        #[unsafe(method_family = none)]
        fn focusItemContainer(&self) -> Option<Retained<ProtocolObject<dyn UIFocusItemContainer>>>;

        /// Marks this environment as needing a focus update, which if accepted will attempt to reset focus to this environment, or one of its preferred focus environments, on the next update cycle. If this environment does not currently contain the focused item, then calling this method has no effect. If a parent of this environment is also requesting focus, then this environment's request is rejected in favor of the parent's.
        /// NOTE: If you provide your own implementation, it must call `[[UIFocusSystem focusSystemForEnvironment:self] requestFocusUpdateToEnvironment:self]`;
        #[unsafe(method(setNeedsFocusUpdate))]
        #[unsafe(method_family = none)]
        fn setNeedsFocusUpdate(&self);

        /// Forces focus to be updated immediately. If there is an environment that has requested a focus update via -setNeedsFocusUpdate, and the request was accepted, then focus will be updated to that environment or one of its preferred focus environments.
        /// NOTE: If you provide your own implementation, it must call `[[UIFocusSystem focusSystemForEnvironment:self] updateFocusIfNeeded];`.
        #[unsafe(method(updateFocusIfNeeded))]
        #[unsafe(method_family = none)]
        fn updateFocusIfNeeded(&self);

        /// Asks whether the system should allow a focus update to occur.
        #[unsafe(method(shouldUpdateFocusInContext:))]
        #[unsafe(method_family = none)]
        fn shouldUpdateFocusInContext(&self, context: &UIFocusUpdateContext) -> bool;

        #[cfg(feature = "UIFocusAnimationCoordinator")]
        /// Called when the screen’s focused item has been updated to a new item. Use the animation coordinator to schedule focus-related animations in response to the update.
        #[unsafe(method(didUpdateFocusInContext:withAnimationCoordinator:))]
        #[unsafe(method_family = none)]
        fn didUpdateFocusInContext_withAnimationCoordinator(
            &self,
            context: &UIFocusUpdateContext,
            coordinator: &UIFocusAnimationCoordinator,
        );

        /// Specifies an identifier corresponding to a sound that should be played for a focus update.
        /// Return UIFocusSoundIdentifierNone to opt out of sounds, UIFocusSoundIdentifierDefault for the system
        /// default sounds, a previously registered identifier for a custom sound, or nil to defer the decision
        /// to the parent.
        #[optional]
        #[unsafe(method(soundIdentifierForFocusUpdateInContext:))]
        #[unsafe(method_family = none)]
        fn soundIdentifierForFocusUpdateInContext(
            &self,
            context: &UIFocusUpdateContext,
        ) -> Option<Retained<UIFocusSoundIdentifier>>;

        #[cfg(all(feature = "UIResponder", feature = "UIView"))]
        #[deprecated]
        #[optional]
        #[unsafe(method(preferredFocusedView))]
        #[unsafe(method_family = none)]
        fn preferredFocusedView(&self) -> Option<Retained<UIView>>;

        /// The identifier of the focus group that this view belongs to. If this is nil, subviews inherit their superview's focus group.
        #[optional]
        #[unsafe(method(focusGroupIdentifier))]
        #[unsafe(method_family = none)]
        fn focusGroupIdentifier(&self) -> Option<Retained<NSString>>;
    }
);

extern_protocol!(
    /// Objects conforming to UIFocusItem are considered capable of participating in focus. Only UIFocusItems can ever be focused.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/uikit/uifocusitem?language=objc)
    pub unsafe trait UIFocusItem: UIFocusEnvironment + MainThreadOnly {
        /// Indicates whether or not this item is currently allowed to become focused.
        /// Returning NO restricts the item from being focusable, even if it is visible in the user interface. For example, UIControls return NO if they are disabled.
        #[unsafe(method(canBecomeFocused))]
        #[unsafe(method_family = none)]
        fn canBecomeFocused(&self) -> bool;

        #[cfg(feature = "objc2-core-foundation")]
        /// The geometric frame of this item, represented in the `coordinateSpace` of the UIFocusItemContainer in which it is contained.
        #[unsafe(method(frame))]
        #[unsafe(method_family = none)]
        fn frame(&self) -> CGRect;

        #[cfg(feature = "UIFocusEffect")]
        /// Describes a visual effect to apply when this item is focused. When not implemented, the system may create a default effect for this item.
        /// Returning nil indicates that the system should not apply any visual effects, and that the app will handle applying the appropriate visuals.
        #[optional]
        #[unsafe(method(focusEffect))]
        #[unsafe(method_family = none)]
        fn focusEffect(&self) -> Option<Retained<UIFocusEffect>>;

        /// The priority this item has in its focus group. The higher the priority, the more likely it is to get picked when focus moves into this group.
        /// Note: this method can only be used to increase an item's priority, not decrease it. For example if an item is currently selected, the actual priority of this item will be determined by MAX(focusGroupPriority, UIFocusGroupPrioritySelected).
        #[optional]
        #[unsafe(method(focusGroupPriority))]
        #[unsafe(method_family = none)]
        fn focusGroupPriority(&self) -> UIFocusGroupPriority;

        /// If this property is present and returns `UIFocusItemDeferralModeNever`, the focus deferral will not be enabled again
        /// after the user engagement timeout has expired if this item is currently focused and programmatic focus updates pointing
        /// to this item will be executed immediatly. If it returns `UIFocusItemDeferralModeAlways` focus will always be deferred
        /// when this item is supposed to be focused.
        /// Does nothing when focus deferral is not supported on the platform.
        #[optional]
        #[unsafe(method(focusItemDeferralMode))]
        #[unsafe(method_family = none)]
        fn focusItemDeferralMode(&self) -> UIFocusItemDeferralMode;

        /// If this returns YES, the focus item is considered transparent in terms of occlusion. Items that are behind it are focusable.
        /// This value is ignored when the item is focusable, in which case the item is never considered transparent.
        #[optional]
        #[unsafe(method(isTransparentFocusItem))]
        #[unsafe(method_family = none)]
        fn isTransparentFocusItem(&self) -> bool;

        #[cfg(feature = "UIFocusMovementHint")]
        /// Called whenever this focus item is hinting to the user a focus movement might occur.
        /// The provided object is mutated by the focus engine whenever the user's finger moves.
        #[optional]
        #[unsafe(method(didHintFocusMovement:))]
        #[unsafe(method_family = none)]
        fn didHintFocusMovement(&self, hint: &UIFocusMovementHint);
    }
);

extern_protocol!(
    /// Objects conforming to UIFocusItemContainer are responsible for providing which focus items they
    /// contain and where they are.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/uikit/uifocusitemcontainer?language=objc)
    pub unsafe trait UIFocusItemContainer: NSObjectProtocol + MainThreadOnly {
        #[cfg(feature = "UIView")]
        /// The coordinate space of the focus items contained in this container. The focus items returned by focusItemsInRect: should report their frames in this coordinate space.
        /// If you are implementing this protocol, you may find it convenient to return the UIScreen as your coordinate space, and ensure that your contained items report their frames in screen space.
        /// Similarly, you might find that your focus items' containing UIView or UIWindow is the most convenient coordinate space to use.
        /// You may also choose to implement your own object that conforms to UICoordinateSpace, if that is the most natural solution for your architecture.
        #[unsafe(method(coordinateSpace))]
        #[unsafe(method_family = none)]
        fn coordinateSpace(&self) -> Retained<ProtocolObject<dyn UICoordinateSpace>>;

        #[cfg(feature = "objc2-core-foundation")]
        /// Returns an array of all focus items within this container that intersect with the provided rect. `rect` is expressed in `coordinateSpace`.
        /// Note: starting in iOS
        /// &
        /// tvOS 16.0, UIView will return its subviews from this method. If you override this method in a UIView subclass, it will be your responsibility to call super and merge your array of custom focus items with UIView's default focus items.
        #[unsafe(method(focusItemsInRect:))]
        #[unsafe(method_family = none)]
        fn focusItemsInRect(
            &self,
            rect: CGRect,
        ) -> Retained<NSArray<ProtocolObject<dyn UIFocusItem>>>;
    }
);

extern_protocol!(
    /// Objects conforming to UIFocusItemScrollableContainer are updated accordingly to ensure the
    /// focused item remains visible on the screen.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/uikit/uifocusitemscrollablecontainer?language=objc)
    pub unsafe trait UIFocusItemScrollableContainer:
        UIFocusItemContainer + MainThreadOnly
    {
        #[cfg(feature = "objc2-core-foundation")]
        /// The current content offset of this scrollable container. If the scrollable container has a `bounds` property, `bounds.origin` must be equal to `contentOffset`.
        #[unsafe(method(contentOffset))]
        #[unsafe(method_family = none)]
        fn contentOffset(&self) -> CGPoint;

        #[cfg(feature = "objc2-core-foundation")]
        /// Setter for [`contentOffset`][Self::contentOffset].
        #[unsafe(method(setContentOffset:))]
        #[unsafe(method_family = none)]
        fn setContentOffset(&self, content_offset: CGPoint);

        #[cfg(feature = "objc2-core-foundation")]
        /// The total size of the content contained by this container. If this size exceeds the size of
        /// this container's visible size, then scrolling is possible.
        #[unsafe(method(contentSize))]
        #[unsafe(method_family = none)]
        fn contentSize(&self) -> CGSize;

        #[cfg(feature = "objc2-core-foundation")]
        /// The visible size of this scrollable container.
        #[unsafe(method(visibleSize))]
        #[unsafe(method_family = none)]
        fn visibleSize(&self) -> CGSize;
    }
);

extern_class!(
    /// UIFocusUpdateContexts provide information relevant to a specific focus update from one view to another. They are ephemeral objects that are usually discarded after the update is finished.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/uikit/uifocusupdatecontext?language=objc)
    #[unsafe(super(NSObject))]
    #[thread_kind = MainThreadOnly]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct UIFocusUpdateContext;
);

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

impl UIFocusUpdateContext {
    extern_methods!(
        /// The item that was focused before the update, i.e. where focus is updating from. May be nil if no item was focused, such as when focus is initially set.
        #[unsafe(method(previouslyFocusedItem))]
        #[unsafe(method_family = none)]
        pub fn previouslyFocusedItem(&self) -> Option<Retained<ProtocolObject<dyn UIFocusItem>>>;

        /// The item that is focused after the update, i.e. where focus is updating to. May be nil if no item is being focused, meaning focus is being lost.
        #[unsafe(method(nextFocusedItem))]
        #[unsafe(method_family = none)]
        pub fn nextFocusedItem(&self) -> Option<Retained<ProtocolObject<dyn UIFocusItem>>>;

        /// The focus heading in which the update is occurring.
        #[unsafe(method(focusHeading))]
        #[unsafe(method_family = none)]
        pub fn focusHeading(&self) -> UIFocusHeading;
    );
}

/// Methods declared on superclass `NSObject`.
impl UIFocusUpdateContext {
    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 "C" {
    /// [Apple's documentation](https://developer.apple.com/documentation/uikit/uifocusdidupdatenotification?language=objc)
    pub static UIFocusDidUpdateNotification: &'static NSNotificationName;
}

extern "C" {
    /// [Apple's documentation](https://developer.apple.com/documentation/uikit/uifocusmovementdidfailnotification?language=objc)
    pub static UIFocusMovementDidFailNotification: &'static NSNotificationName;
}

extern "C" {
    /// [Apple's documentation](https://developer.apple.com/documentation/uikit/uifocusupdatecontextkey?language=objc)
    pub static UIFocusUpdateContextKey: &'static NSString;
}

extern "C" {
    /// [Apple's documentation](https://developer.apple.com/documentation/uikit/uifocusupdateanimationcoordinatorkey?language=objc)
    pub static UIFocusUpdateAnimationCoordinatorKey: &'static NSString;
}

extern "C" {
    /// Sound identifier for disabling sound during a focus update.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/uikit/uifocussoundidentifiernone?language=objc)
    pub static UIFocusSoundIdentifierNone: &'static UIFocusSoundIdentifier;
}

extern "C" {
    /// Sound identifier for playing the default sound during a focus update.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/uikit/uifocussoundidentifierdefault?language=objc)
    pub static UIFocusSoundIdentifierDefault: &'static UIFocusSoundIdentifier;
}
