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

/// [Apple's documentation](https://developer.apple.com/documentation/foundation/nsoperationqueuepriority?language=objc)
// NS_ENUM
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct NSOperationQueuePriority(pub NSInteger);
impl NSOperationQueuePriority {
    #[doc(alias = "NSOperationQueuePriorityVeryLow")]
    pub const VeryLow: Self = Self(-8);
    #[doc(alias = "NSOperationQueuePriorityLow")]
    pub const Low: Self = Self(-4);
    #[doc(alias = "NSOperationQueuePriorityNormal")]
    pub const Normal: Self = Self(0);
    #[doc(alias = "NSOperationQueuePriorityHigh")]
    pub const High: Self = Self(4);
    #[doc(alias = "NSOperationQueuePriorityVeryHigh")]
    pub const VeryHigh: Self = Self(8);
}

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

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

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

unsafe impl Send for NSOperation {}

unsafe impl Sync for NSOperation {}

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

impl NSOperation {
    extern_methods!(
        #[unsafe(method(start))]
        #[unsafe(method_family = none)]
        pub fn start(&self);

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

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

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

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

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

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

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

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

        #[unsafe(method(addDependency:))]
        #[unsafe(method_family = none)]
        pub fn addDependency(&self, op: &NSOperation);

        #[unsafe(method(removeDependency:))]
        #[unsafe(method_family = none)]
        pub fn removeDependency(&self, op: &NSOperation);

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

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

        /// Setter for [`queuePriority`][Self::queuePriority].
        #[unsafe(method(setQueuePriority:))]
        #[unsafe(method_family = none)]
        pub fn setQueuePriority(&self, queue_priority: NSOperationQueuePriority);

        #[cfg(feature = "block2")]
        /// # Safety
        ///
        /// The returned block must be sendable.
        #[unsafe(method(completionBlock))]
        #[unsafe(method_family = none)]
        pub unsafe fn completionBlock(&self) -> *mut block2::DynBlock<dyn Fn()>;

        #[cfg(feature = "block2")]
        /// Setter for [`completionBlock`][Self::completionBlock].
        ///
        /// This is [copied][crate::NSCopying::copy] when set.
        ///
        /// # Safety
        ///
        /// `completion_block` block must be sendable.
        #[unsafe(method(setCompletionBlock:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setCompletionBlock(
            &self,
            completion_block: Option<&block2::DynBlock<dyn Fn()>>,
        );

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

        #[deprecated = "Not supported"]
        #[unsafe(method(threadPriority))]
        #[unsafe(method_family = none)]
        pub fn threadPriority(&self) -> c_double;

        /// Setter for [`threadPriority`][Self::threadPriority].
        #[deprecated = "Not supported"]
        #[unsafe(method(setThreadPriority:))]
        #[unsafe(method_family = none)]
        pub fn setThreadPriority(&self, thread_priority: c_double);

        #[cfg(feature = "NSObjCRuntime")]
        #[unsafe(method(qualityOfService))]
        #[unsafe(method_family = none)]
        pub fn qualityOfService(&self) -> NSQualityOfService;

        #[cfg(feature = "NSObjCRuntime")]
        /// Setter for [`qualityOfService`][Self::qualityOfService].
        #[unsafe(method(setQualityOfService:))]
        #[unsafe(method_family = none)]
        pub fn setQualityOfService(&self, quality_of_service: NSQualityOfService);

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

        #[cfg(feature = "NSString")]
        /// Setter for [`name`][Self::name].
        ///
        /// This is [copied][crate::NSCopying::copy] when set.
        #[unsafe(method(setName:))]
        #[unsafe(method_family = none)]
        pub fn setName(&self, name: Option<&NSString>);
    );
}

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

extern_class!(
    /// [Apple's documentation](https://developer.apple.com/documentation/foundation/nsblockoperation?language=objc)
    #[unsafe(super(NSOperation, NSObject))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct NSBlockOperation;
);

unsafe impl Send for NSBlockOperation {}

unsafe impl Sync for NSBlockOperation {}

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

impl NSBlockOperation {
    extern_methods!(
        #[cfg(feature = "block2")]
        /// # Safety
        ///
        /// `block` block must be sendable.
        #[unsafe(method(blockOperationWithBlock:))]
        #[unsafe(method_family = none)]
        pub unsafe fn blockOperationWithBlock(block: &block2::DynBlock<dyn Fn()>)
            -> Retained<Self>;

        #[cfg(feature = "block2")]
        /// # Safety
        ///
        /// `block` block must be sendable.
        #[unsafe(method(addExecutionBlock:))]
        #[unsafe(method_family = none)]
        pub unsafe fn addExecutionBlock(&self, block: &block2::DynBlock<dyn Fn()>);
    );
}

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

extern_class!(
    /// [Apple's documentation](https://developer.apple.com/documentation/foundation/nsinvocationoperation?language=objc)
    #[unsafe(super(NSOperation, NSObject))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct NSInvocationOperation;
);

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

impl NSInvocationOperation {
    extern_methods!(
        /// # Safety
        ///
        /// - `target` should be of the correct type.
        /// - `sel` must be a valid selector.
        /// - `arg` should be of the correct type.
        #[unsafe(method(initWithTarget:selector:object:))]
        #[unsafe(method_family = init)]
        pub unsafe fn initWithTarget_selector_object(
            this: Allocated<Self>,
            target: &AnyObject,
            sel: Sel,
            arg: Option<&AnyObject>,
        ) -> Option<Retained<Self>>;

        #[cfg(feature = "NSInvocation")]
        #[unsafe(method(initWithInvocation:))]
        #[unsafe(method_family = init)]
        pub unsafe fn initWithInvocation(
            this: Allocated<Self>,
            inv: &NSInvocation,
        ) -> Retained<Self>;

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

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

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

extern "C" {
    /// [Apple's documentation](https://developer.apple.com/documentation/foundation/nsinvocationoperationvoidresultexception?language=objc)
    #[cfg(all(feature = "NSObjCRuntime", feature = "NSString"))]
    pub static NSInvocationOperationVoidResultException: &'static NSExceptionName;
}

extern "C" {
    /// [Apple's documentation](https://developer.apple.com/documentation/foundation/nsinvocationoperationcancelledexception?language=objc)
    #[cfg(all(feature = "NSObjCRuntime", feature = "NSString"))]
    pub static NSInvocationOperationCancelledException: &'static NSExceptionName;
}

/// [Apple's documentation](https://developer.apple.com/documentation/foundation/nsoperationqueuedefaultmaxconcurrentoperationcount?language=objc)
pub static NSOperationQueueDefaultMaxConcurrentOperationCount: NSInteger = -1;

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

unsafe impl Send for NSOperationQueue {}

unsafe impl Sync for NSOperationQueue {}

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

#[cfg(feature = "NSProgress")]
extern_conformance!(
    unsafe impl NSProgressReporting for NSOperationQueue {}
);

impl NSOperationQueue {
    extern_methods!(
        #[cfg(feature = "NSProgress")]
        /// The `progress` property represents a total progress of the operations executed in the queue. By default NSOperationQueue
        /// does not report progress until the `totalUnitCount` of the progress is set. When the `totalUnitCount` property of the progress is set the
        /// queue then opts into participating in progress reporting. When enabled, each operation will contribute 1 unit of completion to the
        /// overall progress of the queue for operations that are finished by the end of main (operations that override start and do not invoke super
        /// will not contribute to progress). Special attention to race conditions should be made when updating the `totalUnitCount` of the progress
        /// as well as care should be taken to avoid 'backwards progress'. For example; when a NSOperationQueue's progress is 5/10, representing 50%
        /// completed, and there are 90 more operations about to be added and the `totalUnitCount` that would then make the progress report as 5/100
        /// which represents 5%. In this example it would mean that any progress bar would jump from displaying 50% back to 5%, which might not be
        /// desirable. In the cases where the `totalUnitCount` needs to be adjusted it is suggested to do this for thread-safety in a barrier by
        /// using the `addBarrierBlock:` API. This ensures that no un-expected execution state occurs adjusting into a potentially backwards moving
        /// progress scenario.
        ///
        ///
        /// NSOperationQueue *queue = [[NSOperationQueue alloc] init];
        /// queue.progress.totalUnitCount = 10;
        #[unsafe(method(progress))]
        #[unsafe(method_family = none)]
        pub fn progress(&self) -> Retained<NSProgress>;

        #[unsafe(method(addOperation:))]
        #[unsafe(method_family = none)]
        pub fn addOperation(&self, op: &NSOperation);

        #[cfg(feature = "NSArray")]
        #[unsafe(method(addOperations:waitUntilFinished:))]
        #[unsafe(method_family = none)]
        pub fn addOperations_waitUntilFinished(&self, ops: &NSArray<NSOperation>, wait: bool);

        #[cfg(feature = "block2")]
        /// # Safety
        ///
        /// `block` block must be sendable.
        #[unsafe(method(addOperationWithBlock:))]
        #[unsafe(method_family = none)]
        pub unsafe fn addOperationWithBlock(&self, block: &block2::DynBlock<dyn Fn()>);

        #[cfg(feature = "block2")]
        /// Parameter `barrier`: A block to execute
        ///
        /// The `addBarrierBlock:` method executes the block when the NSOperationQueue has finished all enqueued operations and
        /// prevents any subsequent operations to be executed until the barrier has been completed. This acts similarly to the
        /// `dispatch_barrier_async` function.
        ///
        /// # Safety
        ///
        /// `barrier` block must be sendable.
        #[unsafe(method(addBarrierBlock:))]
        #[unsafe(method_family = none)]
        pub unsafe fn addBarrierBlock(&self, barrier: &block2::DynBlock<dyn Fn()>);

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

        /// Setter for [`maxConcurrentOperationCount`][Self::maxConcurrentOperationCount].
        #[unsafe(method(setMaxConcurrentOperationCount:))]
        #[unsafe(method_family = none)]
        pub fn setMaxConcurrentOperationCount(&self, max_concurrent_operation_count: NSInteger);

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

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

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

        #[cfg(feature = "NSString")]
        /// Setter for [`name`][Self::name].
        ///
        /// This is [copied][crate::NSCopying::copy] when set.
        #[unsafe(method(setName:))]
        #[unsafe(method_family = none)]
        pub fn setName(&self, name: Option<&NSString>);

        #[cfg(feature = "NSObjCRuntime")]
        #[unsafe(method(qualityOfService))]
        #[unsafe(method_family = none)]
        pub fn qualityOfService(&self) -> NSQualityOfService;

        #[cfg(feature = "NSObjCRuntime")]
        /// Setter for [`qualityOfService`][Self::qualityOfService].
        #[unsafe(method(setQualityOfService:))]
        #[unsafe(method_family = none)]
        pub fn setQualityOfService(&self, quality_of_service: NSQualityOfService);

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

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

        #[unsafe(method(currentQueue))]
        #[unsafe(method_family = none)]
        pub fn currentQueue() -> Option<Retained<NSOperationQueue>>;

        #[unsafe(method(mainQueue))]
        #[unsafe(method_family = none)]
        pub fn mainQueue() -> Retained<NSOperationQueue>;
    );
}

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

/// NSDeprecated.
impl NSOperationQueue {
    extern_methods!(
        #[cfg(feature = "NSArray")]
        #[deprecated = "access to operations is inherently a race condition, it should not be used. For barrier style behaviors please use addBarrierBlock: instead"]
        #[unsafe(method(operations))]
        #[unsafe(method_family = none)]
        pub fn operations(&self) -> Retained<NSArray<NSOperation>>;

        #[deprecated]
        #[unsafe(method(operationCount))]
        #[unsafe(method_family = none)]
        pub fn operationCount(&self) -> NSUInteger;
    );
}
