//
//  SRPhotoplethysmogramSample.h
//  SensorKit
//
//  Copyright © 2023 Apple Inc. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <SensorKit/SRDefines.h>

NS_HEADER_AUDIT_BEGIN(nullability, sendability)

typedef NSString *SRPhotoplethysmogramOpticalSampleCondition NS_TYPED_ENUM API_AVAILABLE(ios(17.4)) API_UNAVAILABLE(watchos, visionos) API_UNAVAILABLE(tvos, macos);
SR_EXTERN SRPhotoplethysmogramOpticalSampleCondition const SRPhotoplethysmogramOpticalSampleConditionSignalSaturation API_AVAILABLE(ios(17.4)) API_UNAVAILABLE(watchos, visionos) API_UNAVAILABLE(tvos, macos);
SR_EXTERN SRPhotoplethysmogramOpticalSampleCondition const SRPhotoplethysmogramOpticalSampleConditionUnreliableNoise API_AVAILABLE(ios(17.4)) API_UNAVAILABLE(watchos, visionos) API_UNAVAILABLE(tvos, macos);

NS_SWIFT_SENDABLE
SR_EXTERN API_AVAILABLE(ios(17.4)) API_UNAVAILABLE(watchos, visionos) API_UNAVAILABLE(tvos, macos)
@interface SRPhotoplethysmogramOpticalSample : NSObject <NSCopying, NSSecureCoding>
- (instancetype)init NS_UNAVAILABLE;
+ (instancetype)new NS_UNAVAILABLE;

/*!
 * @property emitter
 *
 * @brief The index of the LED in use during the sample reading
 *
 */
@property (nonatomic, readonly, assign) NSInteger emitter;

/*!
 * @property activePhotodiodeIndexes
 *
 * @brief The set of photodiodes in use during the sample reading
 *
 */
@property (nonatomic, readonly, strong) NSIndexSet *activePhotodiodeIndexes;

/*!
 * @property signalIdentifier
 *
 * @brief identifier to distinguish between different signals produced 
 * using the same photodiodes and emitters
 *
 * @discussion
 * To provide the same quality of service certain system conditions may require configuring the 
 * PPG sensor behavior differently while using the same photodiodes and emitters. This
 * identifier can be used distinguish between the different signals generated by these
 * different configurations.
 */
@property (nonatomic, readonly, assign) NSInteger signalIdentifier;

/*!
 * @property nominalWavelength
 *
 * @brief the wavelength in nanometers the emitter was designed to produce while
 * operating at a specific temperature
 *
 */
@property (nonatomic, readonly, strong) NSMeasurement<NSUnitLength *> *nominalWavelength;

/*!
 * @property effectiveWavelength
 *
 * @brief a temperature compensated wavelength in nanometers estimate that the emitter is producing
 *
 */
@property (nonatomic, readonly, strong) NSMeasurement<NSUnitLength *> *effectiveWavelength;

/*!
 * @property samplingFrequency
 *
 * @brief Sampling frequency of PPG data in Hz
 *
 */
@property (nonatomic, readonly, strong) NSMeasurement<NSUnitFrequency *> *samplingFrequency;

/*!
 * @property nanosecondsSinceStart
 *
 * @brief nanoseconds since the \c SRPhotoplethysmogramSample start date of the 
 * specific optical sample
 *
 */
@property (nonatomic, readonly, assign) int64_t nanosecondsSinceStart;

/*!
 * @property normalizedReflectance
 *
 * @brief The PPG waveform
 *
 * @discussion This may be \c nil when the sensor data reading is invalid
 *
 */
@property (nonatomic, readonly, strong, nullable) NSNumber *normalizedReflectance NS_REFINED_FOR_SWIFT;

/*!
 * @property whiteNoise
 *
 * @brief White noise estimation
 *
 * @discussion This may be \c nil when the sensor data reading is invalid
 *
 */
@property (nonatomic, readonly, strong, nullable) NSNumber *whiteNoise NS_REFINED_FOR_SWIFT;

/*!
 * @property pinkNoise
 *
 * @brief Pink noise estimation
 *
 * @discussion This may be \c nil when the sensor data reading is invalid
 *
 */
@property (nonatomic, readonly, strong, nullable) NSNumber *pinkNoise NS_REFINED_FOR_SWIFT;

/*!
 * @property backgroundNoise
 *
 * @brief Estimated ambient noise intrusion
 *
 * @discussion This may be \c nil when the sensor data reading is invalid
 *
 */
@property (nonatomic, readonly, strong, nullable) NSNumber *backgroundNoise NS_REFINED_FOR_SWIFT;

/*!
 * @property backgroundNoiseOffset
 *
 * @brief Estimated electronics noise floor level of the sensor
 *
 * @discussion 
 * To estimate the total ambient noise, subtract scaled background noise offset 
 * from the background noise. The scaling factor can be computed based on
 * the researcher's digital filter setup.
 * This may be \c nil when the sensor data reading is invalid
 *
 */
@property (nonatomic, readonly, strong, nullable) NSNumber *backgroundNoiseOffset NS_REFINED_FOR_SWIFT;

/*!
 * @property conditions
 * @brief Flags indicating sensor context or conditions that may effect
 * the sample reading
 *
 * @discussion
 * These flags can provide some indication of data validity or other system conditions
 * that may influence how the recorded data should be treated.
 *
 */
@property (nonatomic, readonly, copy) NSArray<SRPhotoplethysmogramOpticalSampleCondition> *conditions;

@end

NS_SWIFT_SENDABLE
SR_EXTERN API_AVAILABLE(ios(17.4)) API_UNAVAILABLE(watchos, visionos) API_UNAVAILABLE(tvos, macos)
@interface SRPhotoplethysmogramAccelerometerSample : NSObject <NSCopying, NSSecureCoding>
- (instancetype)init NS_UNAVAILABLE;
+ (instancetype)new NS_UNAVAILABLE;

/*!
 * @property nanosecondsSinceStart
 *
 * @brief nanoseconds since the \c SRPhotoplethysmogramSample start date of the specific 
 * accelerometer sample
 *
 */
@property (nonatomic, readonly, assign) int64_t nanosecondsSinceStart;

/*!
 * @property samplingFrequency
 *
 * @brief Sampling frequency of accelerometer data in Hz
 *
 */
@property (nonatomic, readonly, strong) NSMeasurement<NSUnitFrequency *> *samplingFrequency;

/*!
 * @property x
 *
 * @brief X-axis acceleration in G's
 *
 */
@property (nonatomic, readonly, strong) NSMeasurement<NSUnitAcceleration *> *x;

/*!
 * @property y
 *
 * @brief Y-axis acceleration in G's
 *
 */
@property (nonatomic, readonly, strong) NSMeasurement<NSUnitAcceleration *> *y;

/*!
 * @property z
 *
 * @brief Z-axis acceleration in G's
 *
 */
@property (nonatomic, readonly, strong) NSMeasurement<NSUnitAcceleration *> *z;

@end

typedef NSString *SRPhotoplethysmogramSampleUsage NS_TYPED_ENUM API_AVAILABLE(ios(17.4)) API_UNAVAILABLE(watchos, visionos) API_UNAVAILABLE(tvos, macos);

/*!
 * @typedef SRPhotoplethysmogramSampleUsageForegroundHeartRate
 * @brief A heart rate reading actively taken by a user in an app context
 *
 * @discussion
 * Typically driven by the user using the HeartRate app or a workout session.
 */
SR_EXTERN SRPhotoplethysmogramSampleUsage const SRPhotoplethysmogramSampleUsageForegroundHeartRate API_AVAILABLE(ios(17.4)) API_UNAVAILABLE(watchos, visionos) API_UNAVAILABLE(tvos, macos);

/*!
 * @const SRPhotoplethysmogramSampleUsageDeepBreathing
 * @brief A sensor reading actively taken by a user in a deep breathing context
 *
 * @discussion
 * Typically driven by the user performing a reflect or breathe session
 * in the Mindfulness app.
 */
SR_EXTERN SRPhotoplethysmogramSampleUsage const SRPhotoplethysmogramSampleUsageDeepBreathing API_AVAILABLE(ios(17.4)) API_UNAVAILABLE(watchos, visionos) API_UNAVAILABLE(tvos, macos);

/*!
 * @const SRPhotoplethysmogramSampleUsageForegroundBloodOxygen
 * @brief A blood oxygen reading actively taken by a user in app context
 *
 * @discussion
 * Typically driven by the user using the BloodOxygen app
 */
SR_EXTERN SRPhotoplethysmogramSampleUsage const SRPhotoplethysmogramSampleUsageForegroundBloodOxygen API_AVAILABLE(ios(17.4)) API_UNAVAILABLE(watchos, visionos) API_UNAVAILABLE(tvos, macos);

/*!
 * @const SRPhotoplethysmogramSampleUsageBackgroundSystem
 * @brief A sample reading passively taken by the system
 *
 * @discussion
 * These are driven by the system to perform the various heart features of watchOS
 * (e.g., background blood oxygen, afib notifications, low cardio notifications, etc)
 */
SR_EXTERN SRPhotoplethysmogramSampleUsage const SRPhotoplethysmogramSampleUsageBackgroundSystem API_AVAILABLE(ios(17.4)) API_UNAVAILABLE(watchos, visionos) API_UNAVAILABLE(tvos, macos);

NS_SWIFT_SENDABLE
SR_EXTERN API_AVAILABLE(ios(17.4)) API_UNAVAILABLE(watchos, visionos) API_UNAVAILABLE(tvos, macos)
@interface SRPhotoplethysmogramSample : NSObject <NSCopying, NSSecureCoding>
- (instancetype)init NS_UNAVAILABLE;
+ (instancetype)new NS_UNAVAILABLE;

/*!
 * @property startDate
 *
 * @brief the start date of a data collection session
 *
 */
@property (nonatomic, readonly, strong) NSDate *startDate;

/*!
 * @property nanosecondsSinceStart
 *
 * @brief nanoseconds since the start date of this specific sample
 *
 */
@property (nonatomic, readonly, assign) int64_t nanosecondsSinceStart;

/*!
 * @property usage
 * @brief How the sensor was being used during the sample reading
 *
 * @discussion It is possible for these to occur in combination
 */
@property (nonatomic, readonly, copy) NSArray<SRPhotoplethysmogramSampleUsage> *usage;

@property (nonatomic, readonly, copy) NSArray<SRPhotoplethysmogramOpticalSample *> *opticalSamples;

@property (nonatomic, readonly, copy) NSArray<SRPhotoplethysmogramAccelerometerSample *> *accelerometerSamples;

/*!
 * @property temperature
 *
 * @brief temperature of the PPG sensors in the watch, measured in celsius
 *
 * @discussion
 * This may be \c nil when the sensor data reading is invalid or if is not supported by the hardware
 *
 */
@property (nonatomic, readonly, strong, nullable) NSMeasurement<NSUnitTemperature *> *temperature;

@end

NS_HEADER_AUDIT_END(nullability, sendability)
