//! 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::*;

extern_class!(
    /// [Apple's documentation](https://developer.apple.com/documentation/uikit/nsdiffabledatasourcesnapshot?language=objc)
    #[unsafe(super(NSObject))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct NSDiffableDataSourceSnapshot<
        SectionIdentifierType: ?Sized = AnyObject,
        ItemIdentifierType: ?Sized = AnyObject,
    >;
);

impl<SectionIdentifierType: ?Sized + Message, ItemIdentifierType: ?Sized + Message>
    NSDiffableDataSourceSnapshot<SectionIdentifierType, ItemIdentifierType>
{
    /// Unchecked conversion of the generic parameters.
    ///
    /// # Safety
    ///
    /// The generics must be valid to reinterpret as the given types.
    #[inline]
    pub unsafe fn cast_unchecked<
        NewSectionIdentifierType: ?Sized + Message,
        NewItemIdentifierType: ?Sized + Message,
    >(
        &self,
    ) -> &NSDiffableDataSourceSnapshot<NewSectionIdentifierType, NewItemIdentifierType> {
        unsafe { &*((self as *const Self).cast()) }
    }
}

extern_conformance!(
    unsafe impl<SectionIdentifierType: ?Sized, ItemIdentifierType: ?Sized> NSCopying
        for NSDiffableDataSourceSnapshot<SectionIdentifierType, ItemIdentifierType>
    {
    }
);

unsafe impl<SectionIdentifierType: ?Sized + Message, ItemIdentifierType: ?Sized + Message>
    CopyingHelper for NSDiffableDataSourceSnapshot<SectionIdentifierType, ItemIdentifierType>
{
    type Result = Self;
}

extern_conformance!(
    unsafe impl<SectionIdentifierType: ?Sized, ItemIdentifierType: ?Sized> NSObjectProtocol
        for NSDiffableDataSourceSnapshot<SectionIdentifierType, ItemIdentifierType>
    {
    }
);

impl<SectionIdentifierType: Message, ItemIdentifierType: Message>
    NSDiffableDataSourceSnapshot<SectionIdentifierType, ItemIdentifierType>
{
    extern_methods!(
        #[unsafe(method(numberOfItems))]
        #[unsafe(method_family = none)]
        pub fn numberOfItems(&self) -> NSInteger;

        #[unsafe(method(numberOfSections))]
        #[unsafe(method_family = none)]
        pub fn numberOfSections(&self) -> NSInteger;

        #[unsafe(method(sectionIdentifiers))]
        #[unsafe(method_family = none)]
        pub fn sectionIdentifiers(&self) -> Retained<NSArray<SectionIdentifierType>>;

        #[unsafe(method(itemIdentifiers))]
        #[unsafe(method_family = none)]
        pub fn itemIdentifiers(&self) -> Retained<NSArray<ItemIdentifierType>>;

        #[unsafe(method(reloadedSectionIdentifiers))]
        #[unsafe(method_family = none)]
        pub fn reloadedSectionIdentifiers(&self) -> Retained<NSArray<SectionIdentifierType>>;

        #[unsafe(method(reloadedItemIdentifiers))]
        #[unsafe(method_family = none)]
        pub fn reloadedItemIdentifiers(&self) -> Retained<NSArray<ItemIdentifierType>>;

        #[unsafe(method(reconfiguredItemIdentifiers))]
        #[unsafe(method_family = none)]
        pub fn reconfiguredItemIdentifiers(&self) -> Retained<NSArray<ItemIdentifierType>>;

        #[unsafe(method(numberOfItemsInSection:))]
        #[unsafe(method_family = none)]
        pub fn numberOfItemsInSection(
            &self,
            section_identifier: &SectionIdentifierType,
        ) -> NSInteger;

        #[unsafe(method(itemIdentifiersInSectionWithIdentifier:))]
        #[unsafe(method_family = none)]
        pub fn itemIdentifiersInSectionWithIdentifier(
            &self,
            section_identifier: &SectionIdentifierType,
        ) -> Retained<NSArray<ItemIdentifierType>>;

        #[unsafe(method(sectionIdentifierForSectionContainingItemIdentifier:))]
        #[unsafe(method_family = none)]
        pub fn sectionIdentifierForSectionContainingItemIdentifier(
            &self,
            item_identifier: &ItemIdentifierType,
        ) -> Option<Retained<SectionIdentifierType>>;

        #[unsafe(method(indexOfItemIdentifier:))]
        #[unsafe(method_family = none)]
        pub fn indexOfItemIdentifier(&self, item_identifier: &ItemIdentifierType) -> NSInteger;

        #[unsafe(method(indexOfSectionIdentifier:))]
        #[unsafe(method_family = none)]
        pub fn indexOfSectionIdentifier(
            &self,
            section_identifier: &SectionIdentifierType,
        ) -> NSInteger;

        #[unsafe(method(appendItemsWithIdentifiers:))]
        #[unsafe(method_family = none)]
        pub fn appendItemsWithIdentifiers(&self, identifiers: &NSArray<ItemIdentifierType>);

        #[unsafe(method(appendItemsWithIdentifiers:intoSectionWithIdentifier:))]
        #[unsafe(method_family = none)]
        pub fn appendItemsWithIdentifiers_intoSectionWithIdentifier(
            &self,
            identifiers: &NSArray<ItemIdentifierType>,
            section_identifier: &SectionIdentifierType,
        );

        #[unsafe(method(insertItemsWithIdentifiers:beforeItemWithIdentifier:))]
        #[unsafe(method_family = none)]
        pub fn insertItemsWithIdentifiers_beforeItemWithIdentifier(
            &self,
            identifiers: &NSArray<ItemIdentifierType>,
            item_identifier: &ItemIdentifierType,
        );

        #[unsafe(method(insertItemsWithIdentifiers:afterItemWithIdentifier:))]
        #[unsafe(method_family = none)]
        pub fn insertItemsWithIdentifiers_afterItemWithIdentifier(
            &self,
            identifiers: &NSArray<ItemIdentifierType>,
            item_identifier: &ItemIdentifierType,
        );

        #[unsafe(method(deleteItemsWithIdentifiers:))]
        #[unsafe(method_family = none)]
        pub fn deleteItemsWithIdentifiers(&self, identifiers: &NSArray<ItemIdentifierType>);

        #[unsafe(method(deleteAllItems))]
        #[unsafe(method_family = none)]
        pub fn deleteAllItems(&self);

        #[unsafe(method(moveItemWithIdentifier:beforeItemWithIdentifier:))]
        #[unsafe(method_family = none)]
        pub fn moveItemWithIdentifier_beforeItemWithIdentifier(
            &self,
            from_identifier: &ItemIdentifierType,
            to_identifier: &ItemIdentifierType,
        );

        #[unsafe(method(moveItemWithIdentifier:afterItemWithIdentifier:))]
        #[unsafe(method_family = none)]
        pub fn moveItemWithIdentifier_afterItemWithIdentifier(
            &self,
            from_identifier: &ItemIdentifierType,
            to_identifier: &ItemIdentifierType,
        );

        #[unsafe(method(reloadItemsWithIdentifiers:))]
        #[unsafe(method_family = none)]
        pub fn reloadItemsWithIdentifiers(&self, identifiers: &NSArray<ItemIdentifierType>);

        #[unsafe(method(reconfigureItemsWithIdentifiers:))]
        #[unsafe(method_family = none)]
        pub fn reconfigureItemsWithIdentifiers(&self, identifiers: &NSArray<ItemIdentifierType>);

        #[unsafe(method(appendSectionsWithIdentifiers:))]
        #[unsafe(method_family = none)]
        pub fn appendSectionsWithIdentifiers(
            &self,
            section_identifiers: &NSArray<SectionIdentifierType>,
        );

        #[unsafe(method(insertSectionsWithIdentifiers:beforeSectionWithIdentifier:))]
        #[unsafe(method_family = none)]
        pub fn insertSectionsWithIdentifiers_beforeSectionWithIdentifier(
            &self,
            section_identifiers: &NSArray<SectionIdentifierType>,
            to_section_identifier: &SectionIdentifierType,
        );

        #[unsafe(method(insertSectionsWithIdentifiers:afterSectionWithIdentifier:))]
        #[unsafe(method_family = none)]
        pub fn insertSectionsWithIdentifiers_afterSectionWithIdentifier(
            &self,
            section_identifiers: &NSArray<SectionIdentifierType>,
            to_section_identifier: &SectionIdentifierType,
        );

        #[unsafe(method(deleteSectionsWithIdentifiers:))]
        #[unsafe(method_family = none)]
        pub fn deleteSectionsWithIdentifiers(
            &self,
            section_identifiers: &NSArray<SectionIdentifierType>,
        );

        #[unsafe(method(moveSectionWithIdentifier:beforeSectionWithIdentifier:))]
        #[unsafe(method_family = none)]
        pub fn moveSectionWithIdentifier_beforeSectionWithIdentifier(
            &self,
            from_section_identifier: &SectionIdentifierType,
            to_section_identifier: &SectionIdentifierType,
        );

        #[unsafe(method(moveSectionWithIdentifier:afterSectionWithIdentifier:))]
        #[unsafe(method_family = none)]
        pub fn moveSectionWithIdentifier_afterSectionWithIdentifier(
            &self,
            from_section_identifier: &SectionIdentifierType,
            to_section_identifier: &SectionIdentifierType,
        );

        #[unsafe(method(reloadSectionsWithIdentifiers:))]
        #[unsafe(method_family = none)]
        pub fn reloadSectionsWithIdentifiers(
            &self,
            section_identifiers: &NSArray<SectionIdentifierType>,
        );
    );
}

/// Methods declared on superclass `NSObject`.
impl<SectionIdentifierType: Message, ItemIdentifierType: Message>
    NSDiffableDataSourceSnapshot<SectionIdentifierType, ItemIdentifierType>
{
    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() -> Retained<Self>;
    );
}

impl<SectionIdentifierType: Message, ItemIdentifierType: Message> DefaultRetained
    for NSDiffableDataSourceSnapshot<SectionIdentifierType, ItemIdentifierType>
{
    #[inline]
    fn default_retained() -> Retained<Self> {
        Self::new()
    }
}

/// [Apple's documentation](https://developer.apple.com/documentation/uikit/uicollectionviewdiffabledatasourcecellprovider?language=objc)
#[cfg(all(
    feature = "UICollectionView",
    feature = "UICollectionViewCell",
    feature = "UIResponder",
    feature = "UIScrollView",
    feature = "UIView",
    feature = "block2"
))]
pub type UICollectionViewDiffableDataSourceCellProvider = *mut block2::DynBlock<
    dyn Fn(
        NonNull<UICollectionView>,
        NonNull<NSIndexPath>,
        NonNull<AnyObject>,
    ) -> *mut UICollectionViewCell,
>;

/// [Apple's documentation](https://developer.apple.com/documentation/uikit/uicollectionviewdiffabledatasourcesupplementaryviewprovider?language=objc)
#[cfg(all(
    feature = "UICollectionView",
    feature = "UICollectionViewCell",
    feature = "UIResponder",
    feature = "UIScrollView",
    feature = "UIView",
    feature = "block2"
))]
pub type UICollectionViewDiffableDataSourceSupplementaryViewProvider = *mut block2::DynBlock<
    dyn Fn(
        NonNull<UICollectionView>,
        NonNull<NSString>,
        NonNull<NSIndexPath>,
    ) -> *mut UICollectionReusableView,
>;

extern_class!(
    /// [Apple's documentation](https://developer.apple.com/documentation/uikit/nsdiffabledatasourcesectiontransaction?language=objc)
    #[unsafe(super(NSObject))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct NSDiffableDataSourceSectionTransaction<
        SectionIdentifierType: ?Sized = AnyObject,
        ItemIdentifierType: ?Sized = AnyObject,
    >;
);

impl<SectionIdentifierType: ?Sized + Message, ItemIdentifierType: ?Sized + Message>
    NSDiffableDataSourceSectionTransaction<SectionIdentifierType, ItemIdentifierType>
{
    /// Unchecked conversion of the generic parameters.
    ///
    /// # Safety
    ///
    /// The generics must be valid to reinterpret as the given types.
    #[inline]
    pub unsafe fn cast_unchecked<
        NewSectionIdentifierType: ?Sized + Message,
        NewItemIdentifierType: ?Sized + Message,
    >(
        &self,
    ) -> &NSDiffableDataSourceSectionTransaction<NewSectionIdentifierType, NewItemIdentifierType>
    {
        unsafe { &*((self as *const Self).cast()) }
    }
}

extern_conformance!(
    unsafe impl<SectionIdentifierType: ?Sized, ItemIdentifierType: ?Sized> NSObjectProtocol
        for NSDiffableDataSourceSectionTransaction<SectionIdentifierType, ItemIdentifierType>
    {
    }
);

impl<SectionIdentifierType: Message, ItemIdentifierType: Message>
    NSDiffableDataSourceSectionTransaction<SectionIdentifierType, ItemIdentifierType>
{
    extern_methods!(
        /// This property is not atomic.
        ///
        /// # Safety
        ///
        /// This might not be thread-safe.
        #[unsafe(method(sectionIdentifier))]
        #[unsafe(method_family = none)]
        pub unsafe fn sectionIdentifier(&self) -> Retained<SectionIdentifierType>;

        #[cfg(feature = "NSDiffableDataSourceSectionSnapshot")]
        /// This property is not atomic.
        ///
        /// # Safety
        ///
        /// This might not be thread-safe.
        #[unsafe(method(initialSnapshot))]
        #[unsafe(method_family = none)]
        pub unsafe fn initialSnapshot(
            &self,
        ) -> Retained<NSDiffableDataSourceSectionSnapshot<ItemIdentifierType>>;

        #[cfg(feature = "NSDiffableDataSourceSectionSnapshot")]
        /// This property is not atomic.
        ///
        /// # Safety
        ///
        /// This might not be thread-safe.
        #[unsafe(method(finalSnapshot))]
        #[unsafe(method_family = none)]
        pub unsafe fn finalSnapshot(
            &self,
        ) -> Retained<NSDiffableDataSourceSectionSnapshot<ItemIdentifierType>>;

        /// This property is not atomic.
        ///
        /// # Safety
        ///
        /// This might not be thread-safe.
        #[unsafe(method(difference))]
        #[unsafe(method_family = none)]
        pub unsafe fn difference(
            &self,
        ) -> Retained<NSOrderedCollectionDifference<ItemIdentifierType>>;
    );
}

/// Methods declared on superclass `NSObject`.
impl<SectionIdentifierType: Message, ItemIdentifierType: Message>
    NSDiffableDataSourceSectionTransaction<SectionIdentifierType, ItemIdentifierType>
{
    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() -> Retained<Self>;
    );
}

impl<SectionIdentifierType: Message, ItemIdentifierType: Message> DefaultRetained
    for NSDiffableDataSourceSectionTransaction<SectionIdentifierType, ItemIdentifierType>
{
    #[inline]
    fn default_retained() -> Retained<Self> {
        Self::new()
    }
}

extern_class!(
    /// [Apple's documentation](https://developer.apple.com/documentation/uikit/nsdiffabledatasourcetransaction?language=objc)
    #[unsafe(super(NSObject))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct NSDiffableDataSourceTransaction<
        SectionIdentifierType: ?Sized = AnyObject,
        ItemIdentifierType: ?Sized = AnyObject,
    >;
);

impl<SectionIdentifierType: ?Sized + Message, ItemIdentifierType: ?Sized + Message>
    NSDiffableDataSourceTransaction<SectionIdentifierType, ItemIdentifierType>
{
    /// Unchecked conversion of the generic parameters.
    ///
    /// # Safety
    ///
    /// The generics must be valid to reinterpret as the given types.
    #[inline]
    pub unsafe fn cast_unchecked<
        NewSectionIdentifierType: ?Sized + Message,
        NewItemIdentifierType: ?Sized + Message,
    >(
        &self,
    ) -> &NSDiffableDataSourceTransaction<NewSectionIdentifierType, NewItemIdentifierType> {
        unsafe { &*((self as *const Self).cast()) }
    }
}

extern_conformance!(
    unsafe impl<SectionIdentifierType: ?Sized, ItemIdentifierType: ?Sized> NSObjectProtocol
        for NSDiffableDataSourceTransaction<SectionIdentifierType, ItemIdentifierType>
    {
    }
);

impl<SectionIdentifierType: Message, ItemIdentifierType: Message>
    NSDiffableDataSourceTransaction<SectionIdentifierType, ItemIdentifierType>
{
    extern_methods!(
        /// This property is not atomic.
        ///
        /// # Safety
        ///
        /// This might not be thread-safe.
        #[unsafe(method(initialSnapshot))]
        #[unsafe(method_family = none)]
        pub unsafe fn initialSnapshot(
            &self,
        ) -> Retained<NSDiffableDataSourceSnapshot<SectionIdentifierType, ItemIdentifierType>>;

        /// This property is not atomic.
        ///
        /// # Safety
        ///
        /// This might not be thread-safe.
        #[unsafe(method(finalSnapshot))]
        #[unsafe(method_family = none)]
        pub unsafe fn finalSnapshot(
            &self,
        ) -> Retained<NSDiffableDataSourceSnapshot<SectionIdentifierType, ItemIdentifierType>>;

        /// This property is not atomic.
        ///
        /// # Safety
        ///
        /// This might not be thread-safe.
        #[unsafe(method(difference))]
        #[unsafe(method_family = none)]
        pub unsafe fn difference(
            &self,
        ) -> Retained<NSOrderedCollectionDifference<ItemIdentifierType>>;

        /// This property is not atomic.
        ///
        /// # Safety
        ///
        /// This might not be thread-safe.
        #[unsafe(method(sectionTransactions))]
        #[unsafe(method_family = none)]
        pub unsafe fn sectionTransactions(
            &self,
        ) -> Retained<
            NSArray<
                NSDiffableDataSourceSectionTransaction<SectionIdentifierType, ItemIdentifierType>,
            >,
        >;
    );
}

/// Methods declared on superclass `NSObject`.
impl<SectionIdentifierType: Message, ItemIdentifierType: Message>
    NSDiffableDataSourceTransaction<SectionIdentifierType, ItemIdentifierType>
{
    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() -> Retained<Self>;
    );
}

impl<SectionIdentifierType: Message, ItemIdentifierType: Message> DefaultRetained
    for NSDiffableDataSourceTransaction<SectionIdentifierType, ItemIdentifierType>
{
    #[inline]
    fn default_retained() -> Retained<Self> {
        Self::new()
    }
}

extern_class!(
    /// [Apple's documentation](https://developer.apple.com/documentation/uikit/uicollectionviewdiffabledatasourcereorderinghandlers?language=objc)
    #[unsafe(super(NSObject))]
    #[thread_kind = MainThreadOnly]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct UICollectionViewDiffableDataSourceReorderingHandlers<
        SectionType: ?Sized = AnyObject,
        ItemType: ?Sized = AnyObject,
    >;
);

impl<SectionType: ?Sized + Message, ItemType: ?Sized + Message>
    UICollectionViewDiffableDataSourceReorderingHandlers<SectionType, ItemType>
{
    /// Unchecked conversion of the generic parameters.
    ///
    /// # Safety
    ///
    /// The generics must be valid to reinterpret as the given types.
    #[inline]
    pub unsafe fn cast_unchecked<
        NewSectionType: ?Sized + Message,
        NewItemType: ?Sized + Message,
    >(
        &self,
    ) -> &UICollectionViewDiffableDataSourceReorderingHandlers<NewSectionType, NewItemType> {
        unsafe { &*((self as *const Self).cast()) }
    }
}

extern_conformance!(
    unsafe impl<SectionType: ?Sized, ItemType: ?Sized> NSCopying
        for UICollectionViewDiffableDataSourceReorderingHandlers<SectionType, ItemType>
    {
    }
);

unsafe impl<SectionType: ?Sized + Message, ItemType: ?Sized + Message> CopyingHelper
    for UICollectionViewDiffableDataSourceReorderingHandlers<SectionType, ItemType>
{
    type Result = Self;
}

extern_conformance!(
    unsafe impl<SectionType: ?Sized, ItemType: ?Sized> NSObjectProtocol
        for UICollectionViewDiffableDataSourceReorderingHandlers<SectionType, ItemType>
    {
    }
);

impl<SectionType: Message, ItemType: Message>
    UICollectionViewDiffableDataSourceReorderingHandlers<SectionType, ItemType>
{
    extern_methods!(
        #[cfg(feature = "block2")]
        /// # Safety
        ///
        /// The returned block's argument must be a valid pointer.
        #[unsafe(method(canReorderItemHandler))]
        #[unsafe(method_family = none)]
        pub unsafe fn canReorderItemHandler(
            &self,
        ) -> *mut block2::DynBlock<dyn Fn(NonNull<ItemType>) -> Bool>;

        #[cfg(feature = "block2")]
        /// Setter for [`canReorderItemHandler`][Self::canReorderItemHandler].
        ///
        /// This is [copied][objc2_foundation::NSCopying::copy] when set.
        #[unsafe(method(setCanReorderItemHandler:))]
        #[unsafe(method_family = none)]
        pub fn setCanReorderItemHandler(
            &self,
            can_reorder_item_handler: Option<&block2::DynBlock<dyn Fn(NonNull<ItemType>) -> Bool>>,
        );

        #[cfg(feature = "block2")]
        /// # Safety
        ///
        /// The returned block's argument must be a valid pointer.
        #[unsafe(method(willReorderHandler))]
        #[unsafe(method_family = none)]
        pub unsafe fn willReorderHandler(
            &self,
        ) -> *mut block2::DynBlock<
            dyn Fn(NonNull<NSDiffableDataSourceTransaction<SectionType, ItemType>>),
        >;

        #[cfg(feature = "block2")]
        /// Setter for [`willReorderHandler`][Self::willReorderHandler].
        ///
        /// This is [copied][objc2_foundation::NSCopying::copy] when set.
        #[unsafe(method(setWillReorderHandler:))]
        #[unsafe(method_family = none)]
        pub fn setWillReorderHandler(
            &self,
            will_reorder_handler: Option<
                &block2::DynBlock<
                    dyn Fn(NonNull<NSDiffableDataSourceTransaction<SectionType, ItemType>>),
                >,
            >,
        );

        #[cfg(feature = "block2")]
        /// # Safety
        ///
        /// The returned block's argument must be a valid pointer.
        #[unsafe(method(didReorderHandler))]
        #[unsafe(method_family = none)]
        pub unsafe fn didReorderHandler(
            &self,
        ) -> *mut block2::DynBlock<
            dyn Fn(NonNull<NSDiffableDataSourceTransaction<SectionType, ItemType>>),
        >;

        #[cfg(feature = "block2")]
        /// Setter for [`didReorderHandler`][Self::didReorderHandler].
        ///
        /// This is [copied][objc2_foundation::NSCopying::copy] when set.
        #[unsafe(method(setDidReorderHandler:))]
        #[unsafe(method_family = none)]
        pub fn setDidReorderHandler(
            &self,
            did_reorder_handler: Option<
                &block2::DynBlock<
                    dyn Fn(NonNull<NSDiffableDataSourceTransaction<SectionType, ItemType>>),
                >,
            >,
        );
    );
}

/// Methods declared on superclass `NSObject`.
impl<SectionType: Message, ItemType: Message>
    UICollectionViewDiffableDataSourceReorderingHandlers<SectionType, ItemType>
{
    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/uicollectionviewdiffabledatasourcesectionsnapshothandlers?language=objc)
    #[unsafe(super(NSObject))]
    #[thread_kind = MainThreadOnly]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct UICollectionViewDiffableDataSourceSectionSnapshotHandlers<
        ItemType: ?Sized = AnyObject,
    >;
);

impl<ItemType: ?Sized + Message>
    UICollectionViewDiffableDataSourceSectionSnapshotHandlers<ItemType>
{
    /// Unchecked conversion of the generic parameter.
    ///
    /// # Safety
    ///
    /// The generic must be valid to reinterpret as the given type.
    #[inline]
    pub unsafe fn cast_unchecked<NewItemType: ?Sized + Message>(
        &self,
    ) -> &UICollectionViewDiffableDataSourceSectionSnapshotHandlers<NewItemType> {
        unsafe { &*((self as *const Self).cast()) }
    }
}

extern_conformance!(
    unsafe impl<ItemType: ?Sized> NSCopying
        for UICollectionViewDiffableDataSourceSectionSnapshotHandlers<ItemType>
    {
    }
);

unsafe impl<ItemType: ?Sized + Message> CopyingHelper
    for UICollectionViewDiffableDataSourceSectionSnapshotHandlers<ItemType>
{
    type Result = Self;
}

extern_conformance!(
    unsafe impl<ItemType: ?Sized> NSObjectProtocol
        for UICollectionViewDiffableDataSourceSectionSnapshotHandlers<ItemType>
    {
    }
);

impl<ItemType: Message> UICollectionViewDiffableDataSourceSectionSnapshotHandlers<ItemType> {
    extern_methods!(
        #[cfg(feature = "block2")]
        /// # Safety
        ///
        /// The returned block's argument must be a valid pointer.
        #[unsafe(method(shouldExpandItemHandler))]
        #[unsafe(method_family = none)]
        pub unsafe fn shouldExpandItemHandler(
            &self,
        ) -> *mut block2::DynBlock<dyn Fn(NonNull<ItemType>) -> Bool>;

        #[cfg(feature = "block2")]
        /// Setter for [`shouldExpandItemHandler`][Self::shouldExpandItemHandler].
        ///
        /// This is [copied][objc2_foundation::NSCopying::copy] when set.
        #[unsafe(method(setShouldExpandItemHandler:))]
        #[unsafe(method_family = none)]
        pub fn setShouldExpandItemHandler(
            &self,
            should_expand_item_handler: Option<
                &block2::DynBlock<dyn Fn(NonNull<ItemType>) -> Bool>,
            >,
        );

        #[cfg(feature = "block2")]
        /// # Safety
        ///
        /// The returned block's argument must be a valid pointer.
        #[unsafe(method(willExpandItemHandler))]
        #[unsafe(method_family = none)]
        pub unsafe fn willExpandItemHandler(
            &self,
        ) -> *mut block2::DynBlock<dyn Fn(NonNull<ItemType>)>;

        #[cfg(feature = "block2")]
        /// Setter for [`willExpandItemHandler`][Self::willExpandItemHandler].
        ///
        /// This is [copied][objc2_foundation::NSCopying::copy] when set.
        #[unsafe(method(setWillExpandItemHandler:))]
        #[unsafe(method_family = none)]
        pub fn setWillExpandItemHandler(
            &self,
            will_expand_item_handler: Option<&block2::DynBlock<dyn Fn(NonNull<ItemType>)>>,
        );

        #[cfg(feature = "block2")]
        /// # Safety
        ///
        /// The returned block's argument must be a valid pointer.
        #[unsafe(method(shouldCollapseItemHandler))]
        #[unsafe(method_family = none)]
        pub unsafe fn shouldCollapseItemHandler(
            &self,
        ) -> *mut block2::DynBlock<dyn Fn(NonNull<ItemType>) -> Bool>;

        #[cfg(feature = "block2")]
        /// Setter for [`shouldCollapseItemHandler`][Self::shouldCollapseItemHandler].
        ///
        /// This is [copied][objc2_foundation::NSCopying::copy] when set.
        #[unsafe(method(setShouldCollapseItemHandler:))]
        #[unsafe(method_family = none)]
        pub fn setShouldCollapseItemHandler(
            &self,
            should_collapse_item_handler: Option<
                &block2::DynBlock<dyn Fn(NonNull<ItemType>) -> Bool>,
            >,
        );

        #[cfg(feature = "block2")]
        /// # Safety
        ///
        /// The returned block's argument must be a valid pointer.
        #[unsafe(method(willCollapseItemHandler))]
        #[unsafe(method_family = none)]
        pub unsafe fn willCollapseItemHandler(
            &self,
        ) -> *mut block2::DynBlock<dyn Fn(NonNull<ItemType>)>;

        #[cfg(feature = "block2")]
        /// Setter for [`willCollapseItemHandler`][Self::willCollapseItemHandler].
        ///
        /// This is [copied][objc2_foundation::NSCopying::copy] when set.
        #[unsafe(method(setWillCollapseItemHandler:))]
        #[unsafe(method_family = none)]
        pub fn setWillCollapseItemHandler(
            &self,
            will_collapse_item_handler: Option<&block2::DynBlock<dyn Fn(NonNull<ItemType>)>>,
        );

        #[cfg(all(feature = "NSDiffableDataSourceSectionSnapshot", feature = "block2"))]
        /// # Safety
        ///
        /// - The returned block's argument 1 must be a valid pointer.
        /// - The returned block's argument 2 must be a valid pointer.
        #[unsafe(method(snapshotForExpandingParentItemHandler))]
        #[unsafe(method_family = none)]
        pub unsafe fn snapshotForExpandingParentItemHandler(
            &self,
        ) -> *mut block2::DynBlock<
            dyn Fn(
                NonNull<ItemType>,
                NonNull<NSDiffableDataSourceSectionSnapshot<ItemType>>,
            ) -> NonNull<NSDiffableDataSourceSectionSnapshot<ItemType>>,
        >;

        #[cfg(all(feature = "NSDiffableDataSourceSectionSnapshot", feature = "block2"))]
        /// Setter for [`snapshotForExpandingParentItemHandler`][Self::snapshotForExpandingParentItemHandler].
        ///
        /// This is [copied][objc2_foundation::NSCopying::copy] when set.
        ///
        /// # Safety
        ///
        /// `snapshot_for_expanding_parent_item_handler` block's return must be a valid pointer.
        #[unsafe(method(setSnapshotForExpandingParentItemHandler:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setSnapshotForExpandingParentItemHandler(
            &self,
            snapshot_for_expanding_parent_item_handler: Option<
                &block2::DynBlock<
                    dyn Fn(
                        NonNull<ItemType>,
                        NonNull<NSDiffableDataSourceSectionSnapshot<ItemType>>,
                    )
                        -> NonNull<NSDiffableDataSourceSectionSnapshot<ItemType>>,
                >,
            >,
        );
    );
}

/// Methods declared on superclass `NSObject`.
impl<ItemType: Message> UICollectionViewDiffableDataSourceSectionSnapshotHandlers<ItemType> {
    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/uicollectionviewdiffabledatasource?language=objc)
    #[unsafe(super(NSObject))]
    #[thread_kind = MainThreadOnly]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct UICollectionViewDiffableDataSource<
        SectionIdentifierType: ?Sized = AnyObject,
        ItemIdentifierType: ?Sized = AnyObject,
    >;
);

impl<SectionIdentifierType: ?Sized + Message, ItemIdentifierType: ?Sized + Message>
    UICollectionViewDiffableDataSource<SectionIdentifierType, ItemIdentifierType>
{
    /// Unchecked conversion of the generic parameters.
    ///
    /// # Safety
    ///
    /// The generics must be valid to reinterpret as the given types.
    #[inline]
    pub unsafe fn cast_unchecked<
        NewSectionIdentifierType: ?Sized + Message,
        NewItemIdentifierType: ?Sized + Message,
    >(
        &self,
    ) -> &UICollectionViewDiffableDataSource<NewSectionIdentifierType, NewItemIdentifierType> {
        unsafe { &*((self as *const Self).cast()) }
    }
}

extern_conformance!(
    unsafe impl<SectionIdentifierType: ?Sized, ItemIdentifierType: ?Sized> NSObjectProtocol
        for UICollectionViewDiffableDataSource<SectionIdentifierType, ItemIdentifierType>
    {
    }
);

#[cfg(feature = "UICollectionView")]
extern_conformance!(
    unsafe impl<SectionIdentifierType: ?Sized + Message, ItemIdentifierType: ?Sized + Message>
        UICollectionViewDataSource
        for UICollectionViewDiffableDataSource<SectionIdentifierType, ItemIdentifierType>
    {
    }
);

impl<SectionIdentifierType: Message, ItemIdentifierType: Message>
    UICollectionViewDiffableDataSource<SectionIdentifierType, ItemIdentifierType>
{
    extern_methods!(
        #[cfg(all(
            feature = "UICollectionView",
            feature = "UICollectionViewCell",
            feature = "UIResponder",
            feature = "UIScrollView",
            feature = "UIView",
            feature = "block2"
        ))]
        /// # Safety
        ///
        /// `cell_provider` must be a valid pointer.
        #[unsafe(method(initWithCollectionView:cellProvider:))]
        #[unsafe(method_family = init)]
        pub unsafe fn initWithCollectionView_cellProvider(
            this: Allocated<Self>,
            collection_view: &UICollectionView,
            cell_provider: UICollectionViewDiffableDataSourceCellProvider,
        ) -> Retained<Self>;

        #[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>;

        #[cfg(all(
            feature = "UICollectionView",
            feature = "UICollectionViewCell",
            feature = "UIResponder",
            feature = "UIScrollView",
            feature = "UIView",
            feature = "block2"
        ))]
        /// # Safety
        ///
        /// - The returned block's argument 1 must be a valid pointer.
        /// - The returned block's argument 2 must be a valid pointer.
        /// - The returned block's argument 3 must be a valid pointer.
        #[unsafe(method(supplementaryViewProvider))]
        #[unsafe(method_family = none)]
        pub unsafe fn supplementaryViewProvider(
            &self,
        ) -> UICollectionViewDiffableDataSourceSupplementaryViewProvider;

        #[cfg(all(
            feature = "UICollectionView",
            feature = "UICollectionViewCell",
            feature = "UIResponder",
            feature = "UIScrollView",
            feature = "UIView",
            feature = "block2"
        ))]
        /// Setter for [`supplementaryViewProvider`][Self::supplementaryViewProvider].
        ///
        /// This is [copied][objc2_foundation::NSCopying::copy] when set.
        ///
        /// # Safety
        ///
        /// `supplementary_view_provider` must be a valid pointer or null.
        #[unsafe(method(setSupplementaryViewProvider:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setSupplementaryViewProvider(
            &self,
            supplementary_view_provider: UICollectionViewDiffableDataSourceSupplementaryViewProvider,
        );

        #[unsafe(method(snapshot))]
        #[unsafe(method_family = none)]
        pub fn snapshot(
            &self,
        ) -> Retained<NSDiffableDataSourceSnapshot<SectionIdentifierType, ItemIdentifierType>>;

        #[unsafe(method(applySnapshot:animatingDifferences:))]
        #[unsafe(method_family = none)]
        pub fn applySnapshot_animatingDifferences(
            &self,
            snapshot: &NSDiffableDataSourceSnapshot<SectionIdentifierType, ItemIdentifierType>,
            animating_differences: bool,
        );

        #[cfg(feature = "block2")]
        #[unsafe(method(applySnapshot:animatingDifferences:completion:))]
        #[unsafe(method_family = none)]
        pub fn applySnapshot_animatingDifferences_completion(
            &self,
            snapshot: &NSDiffableDataSourceSnapshot<SectionIdentifierType, ItemIdentifierType>,
            animating_differences: bool,
            completion: Option<&block2::DynBlock<dyn Fn()>>,
        );

        #[unsafe(method(applySnapshotUsingReloadData:))]
        #[unsafe(method_family = none)]
        pub fn applySnapshotUsingReloadData(
            &self,
            snapshot: &NSDiffableDataSourceSnapshot<SectionIdentifierType, ItemIdentifierType>,
        );

        #[cfg(feature = "block2")]
        #[unsafe(method(applySnapshotUsingReloadData:completion:))]
        #[unsafe(method_family = none)]
        pub fn applySnapshotUsingReloadData_completion(
            &self,
            snapshot: &NSDiffableDataSourceSnapshot<SectionIdentifierType, ItemIdentifierType>,
            completion: Option<&block2::DynBlock<dyn Fn()>>,
        );

        #[unsafe(method(sectionIdentifierForIndex:))]
        #[unsafe(method_family = none)]
        pub fn sectionIdentifierForIndex(
            &self,
            index: NSInteger,
        ) -> Option<Retained<SectionIdentifierType>>;

        #[unsafe(method(indexForSectionIdentifier:))]
        #[unsafe(method_family = none)]
        pub fn indexForSectionIdentifier(&self, identifier: &SectionIdentifierType) -> NSInteger;

        #[unsafe(method(itemIdentifierForIndexPath:))]
        #[unsafe(method_family = none)]
        pub fn itemIdentifierForIndexPath(
            &self,
            index_path: &NSIndexPath,
        ) -> Option<Retained<ItemIdentifierType>>;

        #[unsafe(method(indexPathForItemIdentifier:))]
        #[unsafe(method_family = none)]
        pub fn indexPathForItemIdentifier(
            &self,
            identifier: &ItemIdentifierType,
        ) -> Option<Retained<NSIndexPath>>;

        #[unsafe(method(reorderingHandlers))]
        #[unsafe(method_family = none)]
        pub fn reorderingHandlers(
            &self,
        ) -> Retained<
            UICollectionViewDiffableDataSourceReorderingHandlers<
                SectionIdentifierType,
                ItemIdentifierType,
            >,
        >;

        /// Setter for [`reorderingHandlers`][Self::reorderingHandlers].
        ///
        /// This is [copied][objc2_foundation::NSCopying::copy] when set.
        #[unsafe(method(setReorderingHandlers:))]
        #[unsafe(method_family = none)]
        pub fn setReorderingHandlers(
            &self,
            reordering_handlers: &UICollectionViewDiffableDataSourceReorderingHandlers<
                SectionIdentifierType,
                ItemIdentifierType,
            >,
        );

        #[cfg(feature = "NSDiffableDataSourceSectionSnapshot")]
        #[unsafe(method(applySnapshot:toSection:animatingDifferences:))]
        #[unsafe(method_family = none)]
        pub fn applySnapshot_toSection_animatingDifferences(
            &self,
            snapshot: &NSDiffableDataSourceSectionSnapshot<ItemIdentifierType>,
            section_identifier: &SectionIdentifierType,
            animating_differences: bool,
        );

        #[cfg(all(feature = "NSDiffableDataSourceSectionSnapshot", feature = "block2"))]
        #[unsafe(method(applySnapshot:toSection:animatingDifferences:completion:))]
        #[unsafe(method_family = none)]
        pub fn applySnapshot_toSection_animatingDifferences_completion(
            &self,
            snapshot: &NSDiffableDataSourceSectionSnapshot<ItemIdentifierType>,
            section_identifier: &SectionIdentifierType,
            animating_differences: bool,
            completion: Option<&block2::DynBlock<dyn Fn()>>,
        );

        #[cfg(feature = "NSDiffableDataSourceSectionSnapshot")]
        #[unsafe(method(snapshotForSection:))]
        #[unsafe(method_family = none)]
        pub fn snapshotForSection(
            &self,
            section: &SectionIdentifierType,
        ) -> Retained<NSDiffableDataSourceSectionSnapshot<ItemIdentifierType>>;

        #[unsafe(method(sectionSnapshotHandlers))]
        #[unsafe(method_family = none)]
        pub fn sectionSnapshotHandlers(
            &self,
        ) -> Retained<UICollectionViewDiffableDataSourceSectionSnapshotHandlers<ItemIdentifierType>>;

        /// Setter for [`sectionSnapshotHandlers`][Self::sectionSnapshotHandlers].
        ///
        /// This is [copied][objc2_foundation::NSCopying::copy] when set.
        #[unsafe(method(setSectionSnapshotHandlers:))]
        #[unsafe(method_family = none)]
        pub fn setSectionSnapshotHandlers(
            &self,
            section_snapshot_handlers: &UICollectionViewDiffableDataSourceSectionSnapshotHandlers<
                ItemIdentifierType,
            >,
        );
    );
}

/// [Apple's documentation](https://developer.apple.com/documentation/uikit/uitableviewdiffabledatasourcecellprovider?language=objc)
#[cfg(all(
    feature = "UIResponder",
    feature = "UIScrollView",
    feature = "UITableView",
    feature = "UITableViewCell",
    feature = "UIView",
    feature = "block2"
))]
pub type UITableViewDiffableDataSourceCellProvider = *mut block2::DynBlock<
    dyn Fn(NonNull<UITableView>, NonNull<NSIndexPath>, NonNull<AnyObject>) -> *mut UITableViewCell,
>;

extern_class!(
    /// [Apple's documentation](https://developer.apple.com/documentation/uikit/uitableviewdiffabledatasource?language=objc)
    #[unsafe(super(NSObject))]
    #[thread_kind = MainThreadOnly]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct UITableViewDiffableDataSource<
        SectionIdentifierType: ?Sized = AnyObject,
        ItemIdentifierType: ?Sized = AnyObject,
    >;
);

impl<SectionIdentifierType: ?Sized + Message, ItemIdentifierType: ?Sized + Message>
    UITableViewDiffableDataSource<SectionIdentifierType, ItemIdentifierType>
{
    /// Unchecked conversion of the generic parameters.
    ///
    /// # Safety
    ///
    /// The generics must be valid to reinterpret as the given types.
    #[inline]
    pub unsafe fn cast_unchecked<
        NewSectionIdentifierType: ?Sized + Message,
        NewItemIdentifierType: ?Sized + Message,
    >(
        &self,
    ) -> &UITableViewDiffableDataSource<NewSectionIdentifierType, NewItemIdentifierType> {
        unsafe { &*((self as *const Self).cast()) }
    }
}

extern_conformance!(
    unsafe impl<SectionIdentifierType: ?Sized, ItemIdentifierType: ?Sized> NSObjectProtocol
        for UITableViewDiffableDataSource<SectionIdentifierType, ItemIdentifierType>
    {
    }
);

#[cfg(feature = "UITableView")]
extern_conformance!(
    unsafe impl<SectionIdentifierType: ?Sized + Message, ItemIdentifierType: ?Sized + Message>
        UITableViewDataSource
        for UITableViewDiffableDataSource<SectionIdentifierType, ItemIdentifierType>
    {
    }
);

impl<SectionIdentifierType: Message, ItemIdentifierType: Message>
    UITableViewDiffableDataSource<SectionIdentifierType, ItemIdentifierType>
{
    extern_methods!(
        #[cfg(all(
            feature = "UIResponder",
            feature = "UIScrollView",
            feature = "UITableView",
            feature = "UITableViewCell",
            feature = "UIView",
            feature = "block2"
        ))]
        /// # Safety
        ///
        /// `cell_provider` must be a valid pointer.
        #[unsafe(method(initWithTableView:cellProvider:))]
        #[unsafe(method_family = init)]
        pub unsafe fn initWithTableView_cellProvider(
            this: Allocated<Self>,
            table_view: &UITableView,
            cell_provider: UITableViewDiffableDataSourceCellProvider,
        ) -> Retained<Self>;

        #[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>;

        #[unsafe(method(snapshot))]
        #[unsafe(method_family = none)]
        pub fn snapshot(
            &self,
        ) -> Retained<NSDiffableDataSourceSnapshot<SectionIdentifierType, ItemIdentifierType>>;

        #[unsafe(method(applySnapshot:animatingDifferences:))]
        #[unsafe(method_family = none)]
        pub fn applySnapshot_animatingDifferences(
            &self,
            snapshot: &NSDiffableDataSourceSnapshot<SectionIdentifierType, ItemIdentifierType>,
            animating_differences: bool,
        );

        #[cfg(feature = "block2")]
        #[unsafe(method(applySnapshot:animatingDifferences:completion:))]
        #[unsafe(method_family = none)]
        pub fn applySnapshot_animatingDifferences_completion(
            &self,
            snapshot: &NSDiffableDataSourceSnapshot<SectionIdentifierType, ItemIdentifierType>,
            animating_differences: bool,
            completion: Option<&block2::DynBlock<dyn Fn()>>,
        );

        #[unsafe(method(applySnapshotUsingReloadData:))]
        #[unsafe(method_family = none)]
        pub fn applySnapshotUsingReloadData(
            &self,
            snapshot: &NSDiffableDataSourceSnapshot<SectionIdentifierType, ItemIdentifierType>,
        );

        #[cfg(feature = "block2")]
        #[unsafe(method(applySnapshotUsingReloadData:completion:))]
        #[unsafe(method_family = none)]
        pub fn applySnapshotUsingReloadData_completion(
            &self,
            snapshot: &NSDiffableDataSourceSnapshot<SectionIdentifierType, ItemIdentifierType>,
            completion: Option<&block2::DynBlock<dyn Fn()>>,
        );

        #[unsafe(method(sectionIdentifierForIndex:))]
        #[unsafe(method_family = none)]
        pub fn sectionIdentifierForIndex(
            &self,
            index: NSInteger,
        ) -> Option<Retained<SectionIdentifierType>>;

        #[unsafe(method(indexForSectionIdentifier:))]
        #[unsafe(method_family = none)]
        pub fn indexForSectionIdentifier(&self, identifier: &SectionIdentifierType) -> NSInteger;

        #[unsafe(method(itemIdentifierForIndexPath:))]
        #[unsafe(method_family = none)]
        pub fn itemIdentifierForIndexPath(
            &self,
            index_path: &NSIndexPath,
        ) -> Option<Retained<ItemIdentifierType>>;

        #[unsafe(method(indexPathForItemIdentifier:))]
        #[unsafe(method_family = none)]
        pub fn indexPathForItemIdentifier(
            &self,
            identifier: &ItemIdentifierType,
        ) -> Option<Retained<NSIndexPath>>;

        #[cfg(feature = "UITableView")]
        #[unsafe(method(defaultRowAnimation))]
        #[unsafe(method_family = none)]
        pub fn defaultRowAnimation(&self) -> UITableViewRowAnimation;

        #[cfg(feature = "UITableView")]
        /// Setter for [`defaultRowAnimation`][Self::defaultRowAnimation].
        #[unsafe(method(setDefaultRowAnimation:))]
        #[unsafe(method_family = none)]
        pub fn setDefaultRowAnimation(&self, default_row_animation: UITableViewRowAnimation);
    );
}
