//! 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/coredata/nsfetchedresultscontroller?language=objc)
    #[unsafe(super(NSObject))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    #[cfg(feature = "NSFetchRequest")]
    pub struct NSFetchedResultsController<ResultType: ?Sized = AnyObject>;
);

#[cfg(feature = "NSFetchRequest")]
impl<ResultType: ?Sized + Message + NSFetchRequestResult> NSFetchedResultsController<ResultType> {
    /// Unchecked conversion of the generic parameter.
    ///
    /// # Safety
    ///
    /// The generic must be valid to reinterpret as the given type.
    #[inline]
    pub unsafe fn cast_unchecked<NewResultType: ?Sized + Message + NSFetchRequestResult>(
        &self,
    ) -> &NSFetchedResultsController<NewResultType> {
        unsafe { &*((self as *const Self).cast()) }
    }
}

#[cfg(feature = "NSFetchRequest")]
extern_conformance!(
    unsafe impl<ResultType: ?Sized + NSFetchRequestResult> NSObjectProtocol
        for NSFetchedResultsController<ResultType>
    {
    }
);

#[cfg(feature = "NSFetchRequest")]
impl<ResultType: Message + NSFetchRequestResult> NSFetchedResultsController<ResultType> {
    extern_methods!(
        #[cfg(all(
            feature = "NSManagedObjectContext",
            feature = "NSPersistentStoreRequest"
        ))]
        #[unsafe(method(initWithFetchRequest:managedObjectContext:sectionNameKeyPath:cacheName:))]
        #[unsafe(method_family = init)]
        pub unsafe fn initWithFetchRequest_managedObjectContext_sectionNameKeyPath_cacheName(
            this: Allocated<Self>,
            fetch_request: &NSFetchRequest<ResultType>,
            context: &NSManagedObjectContext,
            section_name_key_path: Option<&NSString>,
            name: Option<&NSString>,
        ) -> Retained<Self>;

        #[unsafe(method(performFetch:_))]
        #[unsafe(method_family = none)]
        pub unsafe fn performFetch(&self) -> Result<(), Retained<NSError>>;

        #[cfg(feature = "NSPersistentStoreRequest")]
        #[unsafe(method(fetchRequest))]
        #[unsafe(method_family = none)]
        pub unsafe fn fetchRequest(&self) -> Retained<NSFetchRequest<ResultType>>;

        #[cfg(feature = "NSManagedObjectContext")]
        #[unsafe(method(managedObjectContext))]
        #[unsafe(method_family = none)]
        pub unsafe fn managedObjectContext(&self) -> Retained<NSManagedObjectContext>;

        #[unsafe(method(sectionNameKeyPath))]
        #[unsafe(method_family = none)]
        pub unsafe fn sectionNameKeyPath(&self) -> Option<Retained<NSString>>;

        #[unsafe(method(cacheName))]
        #[unsafe(method_family = none)]
        pub unsafe fn cacheName(&self) -> Option<Retained<NSString>>;

        /// # Safety
        ///
        /// This is not retained internally, you must ensure the object is still alive.
        #[unsafe(method(delegate))]
        #[unsafe(method_family = none)]
        pub unsafe fn delegate(
            &self,
        ) -> Option<Retained<ProtocolObject<dyn NSFetchedResultsControllerDelegate>>>;

        /// Setter for [`delegate`][Self::delegate].
        ///
        /// # Safety
        ///
        /// This is unretained, you must ensure the object is kept alive while in use.
        #[unsafe(method(setDelegate:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setDelegate(
            &self,
            delegate: Option<&ProtocolObject<dyn NSFetchedResultsControllerDelegate>>,
        );

        #[unsafe(method(deleteCacheWithName:))]
        #[unsafe(method_family = none)]
        pub unsafe fn deleteCacheWithName(name: Option<&NSString>);

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

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

        #[unsafe(method(indexPathForObject:))]
        #[unsafe(method_family = none)]
        pub unsafe fn indexPathForObject(
            &self,
            object: &ResultType,
        ) -> Option<Retained<NSIndexPath>>;

        #[unsafe(method(sectionIndexTitleForSectionName:))]
        #[unsafe(method_family = none)]
        pub unsafe fn sectionIndexTitleForSectionName(
            &self,
            section_name: &NSString,
        ) -> Option<Retained<NSString>>;

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

        #[unsafe(method(sections))]
        #[unsafe(method_family = none)]
        pub unsafe fn sections(
            &self,
        ) -> Option<Retained<NSArray<ProtocolObject<dyn NSFetchedResultsSectionInfo>>>>;

        #[unsafe(method(sectionForSectionIndexTitle:atIndex:))]
        #[unsafe(method_family = none)]
        pub unsafe fn sectionForSectionIndexTitle_atIndex(
            &self,
            title: &NSString,
            section_index: NSInteger,
        ) -> NSInteger;
    );
}

/// Methods declared on superclass `NSObject`.
#[cfg(feature = "NSFetchRequest")]
impl<ResultType: Message + NSFetchRequestResult> NSFetchedResultsController<ResultType> {
    extern_methods!(
        #[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() -> Retained<Self>;
    );
}

extern_protocol!(
    /// [Apple's documentation](https://developer.apple.com/documentation/coredata/nsfetchedresultssectioninfo?language=objc)
    pub unsafe trait NSFetchedResultsSectionInfo {
        #[unsafe(method(name))]
        #[unsafe(method_family = none)]
        unsafe fn name(&self) -> Retained<NSString>;

        #[unsafe(method(indexTitle))]
        #[unsafe(method_family = none)]
        unsafe fn indexTitle(&self) -> Option<Retained<NSString>>;

        #[unsafe(method(numberOfObjects))]
        #[unsafe(method_family = none)]
        unsafe fn numberOfObjects(&self) -> NSUInteger;

        #[unsafe(method(objects))]
        #[unsafe(method_family = none)]
        unsafe fn objects(&self) -> Option<Retained<NSArray>>;
    }
);

/// [Apple's documentation](https://developer.apple.com/documentation/coredata/nsfetchedresultschangetype?language=objc)
// NS_ENUM
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct NSFetchedResultsChangeType(pub NSUInteger);
impl NSFetchedResultsChangeType {
    #[doc(alias = "NSFetchedResultsChangeInsert")]
    pub const Insert: Self = Self(1);
    #[doc(alias = "NSFetchedResultsChangeDelete")]
    pub const Delete: Self = Self(2);
    #[doc(alias = "NSFetchedResultsChangeMove")]
    pub const Move: Self = Self(3);
    #[doc(alias = "NSFetchedResultsChangeUpdate")]
    pub const Update: Self = Self(4);
}

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

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

extern_protocol!(
    /// [Apple's documentation](https://developer.apple.com/documentation/coredata/nsfetchedresultscontrollerdelegate?language=objc)
    pub unsafe trait NSFetchedResultsControllerDelegate: NSObjectProtocol {
        #[cfg(all(feature = "NSFetchRequest", feature = "NSManagedObjectID"))]
        /// # Safety
        ///
        /// `controller` generic should be bound by `NSFetchRequestResult`.
        #[optional]
        #[unsafe(method(controller:didChangeContentWithDifference:))]
        #[unsafe(method_family = none)]
        unsafe fn controller_didChangeContentWithDifference(
            &self,
            controller: &NSFetchedResultsController,
            diff: &NSOrderedCollectionDifference<NSManagedObjectID>,
        );

        #[cfg(feature = "NSFetchRequest")]
        /// # Safety
        ///
        /// - `controller` generic should be bound by `NSFetchRequestResult`.
        /// - `an_object` should be of the correct type.
        #[optional]
        #[unsafe(method(controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:))]
        #[unsafe(method_family = none)]
        unsafe fn controller_didChangeObject_atIndexPath_forChangeType_newIndexPath(
            &self,
            controller: &NSFetchedResultsController,
            an_object: &AnyObject,
            index_path: Option<&NSIndexPath>,
            r#type: NSFetchedResultsChangeType,
            new_index_path: Option<&NSIndexPath>,
        );

        #[cfg(feature = "NSFetchRequest")]
        /// # Safety
        ///
        /// `controller` generic should be bound by `NSFetchRequestResult`.
        #[optional]
        #[unsafe(method(controller:didChangeSection:atIndex:forChangeType:))]
        #[unsafe(method_family = none)]
        unsafe fn controller_didChangeSection_atIndex_forChangeType(
            &self,
            controller: &NSFetchedResultsController,
            section_info: &ProtocolObject<dyn NSFetchedResultsSectionInfo>,
            section_index: NSUInteger,
            r#type: NSFetchedResultsChangeType,
        );

        #[cfg(feature = "NSFetchRequest")]
        /// # Safety
        ///
        /// `controller` generic should be bound by `NSFetchRequestResult`.
        #[optional]
        #[unsafe(method(controllerWillChangeContent:))]
        #[unsafe(method_family = none)]
        unsafe fn controllerWillChangeContent(&self, controller: &NSFetchedResultsController);

        #[cfg(feature = "NSFetchRequest")]
        /// # Safety
        ///
        /// `controller` generic should be bound by `NSFetchRequestResult`.
        #[optional]
        #[unsafe(method(controllerDidChangeContent:))]
        #[unsafe(method_family = none)]
        unsafe fn controllerDidChangeContent(&self, controller: &NSFetchedResultsController);

        #[cfg(feature = "NSFetchRequest")]
        /// # Safety
        ///
        /// `controller` generic should be bound by `NSFetchRequestResult`.
        #[optional]
        #[unsafe(method(controller:sectionIndexTitleForSectionName:))]
        #[unsafe(method_family = none)]
        unsafe fn controller_sectionIndexTitleForSectionName(
            &self,
            controller: &NSFetchedResultsController,
            section_name: &NSString,
        ) -> Option<Retained<NSString>>;
    }
);
