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

use crate::*;

/// Options supported by methods that produce difference objects.
///
/// See also [Apple's documentation](https://developer.apple.com/documentation/foundation/nsorderedcollectiondifferencecalculationoptions?language=objc)
// NS_OPTIONS
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct NSOrderedCollectionDifferenceCalculationOptions(pub NSUInteger);
bitflags::bitflags! {
    impl NSOrderedCollectionDifferenceCalculationOptions: NSUInteger {
/// Insertion changes do not store a reference to the inserted object.
        #[doc(alias = "NSOrderedCollectionDifferenceCalculationOmitInsertedObjects")]
        const OmitInsertedObjects = 1<<0;
/// Insertion changes do not store a reference to the removed object.
        #[doc(alias = "NSOrderedCollectionDifferenceCalculationOmitRemovedObjects")]
        const OmitRemovedObjects = 1<<1;
/// Assume objects that were uniquely removed and inserted were moved.
/// This is useful when diffing based on identity instead of equality.
        #[doc(alias = "NSOrderedCollectionDifferenceCalculationInferMoves")]
        const InferMoves = 1<<2;
    }
}

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

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

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

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

#[cfg(feature = "NSEnumerator")]
extern_conformance!(
    unsafe impl<ObjectType: ?Sized> NSFastEnumeration for NSOrderedCollectionDifference<ObjectType> {}
);

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

impl<ObjectType: Message> NSOrderedCollectionDifference<ObjectType> {
    extern_methods!(
        #[cfg(all(feature = "NSArray", feature = "NSOrderedCollectionChange"))]
        /// Creates a new difference representing the changes in the parameter.
        ///
        /// For clients interested in the difference between two collections, the
        /// collection's differenceFrom method should be used instead.
        ///
        /// To guarantee that instances are unambiguous and safe for compatible base
        /// states, this method requires that its parameter conform to the following
        /// requirements:
        ///
        /// 1) All insertion offsets are unique
        /// 2) All removal offsets are unique
        /// 3) All associated indexes match a change with the opposite parity.
        #[unsafe(method(initWithChanges:))]
        #[unsafe(method_family = init)]
        pub fn initWithChanges(
            this: Allocated<Self>,
            changes: &NSArray<NSOrderedCollectionChange<ObjectType>>,
        ) -> Retained<Self>;

        #[cfg(all(
            feature = "NSArray",
            feature = "NSIndexSet",
            feature = "NSOrderedCollectionChange"
        ))]
        #[unsafe(method(initWithInsertIndexes:insertedObjects:removeIndexes:removedObjects:additionalChanges:))]
        #[unsafe(method_family = init)]
        pub fn initWithInsertIndexes_insertedObjects_removeIndexes_removedObjects_additionalChanges(
            this: Allocated<Self>,
            inserts: &NSIndexSet,
            inserted_objects: Option<&NSArray<ObjectType>>,
            removes: &NSIndexSet,
            removed_objects: Option<&NSArray<ObjectType>>,
            changes: &NSArray<NSOrderedCollectionChange<ObjectType>>,
        ) -> Retained<Self>;

        #[cfg(all(feature = "NSArray", feature = "NSIndexSet"))]
        #[unsafe(method(initWithInsertIndexes:insertedObjects:removeIndexes:removedObjects:))]
        #[unsafe(method_family = init)]
        pub fn initWithInsertIndexes_insertedObjects_removeIndexes_removedObjects(
            this: Allocated<Self>,
            inserts: &NSIndexSet,
            inserted_objects: Option<&NSArray<ObjectType>>,
            removes: &NSIndexSet,
            removed_objects: Option<&NSArray<ObjectType>>,
        ) -> Retained<Self>;

        #[cfg(all(feature = "NSArray", feature = "NSOrderedCollectionChange"))]
        #[unsafe(method(insertions))]
        #[unsafe(method_family = none)]
        pub fn insertions(&self) -> Retained<NSArray<NSOrderedCollectionChange<ObjectType>>>;

        #[cfg(all(feature = "NSArray", feature = "NSOrderedCollectionChange"))]
        #[unsafe(method(removals))]
        #[unsafe(method_family = none)]
        pub fn removals(&self) -> Retained<NSArray<NSOrderedCollectionChange<ObjectType>>>;

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

        #[cfg(all(feature = "NSOrderedCollectionChange", feature = "block2"))]
        /// # Safety
        ///
        /// `block` block's return must be a valid pointer.
        #[unsafe(method(differenceByTransformingChangesWithBlock:))]
        #[unsafe(method_family = none)]
        pub unsafe fn differenceByTransformingChangesWithBlock(
            &self,
            block: &block2::DynBlock<
                dyn Fn(
                        NonNull<NSOrderedCollectionChange<ObjectType>>,
                    ) -> NonNull<NSOrderedCollectionChange<AnyObject>>
                    + '_,
            >,
        ) -> Retained<NSOrderedCollectionDifference<AnyObject>>;

        #[unsafe(method(inverseDifference))]
        #[unsafe(method_family = none)]
        pub fn inverseDifference(&self) -> Retained<Self>;
    );
}

/// Methods declared on superclass `NSObject`.
impl<ObjectType: Message> NSOrderedCollectionDifference<ObjectType> {
    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<ObjectType: Message> DefaultRetained for NSOrderedCollectionDifference<ObjectType> {
    #[inline]
    fn default_retained() -> Retained<Self> {
        Self::new()
    }
}
