//
//  HS2S.h
//  iHealthSDKStatic
//
//  Created by Lei Bao on 2022/8/8.
//  Copyright © 2019 ihealthSDK. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "HSMacroFile.h"

NS_ASSUME_NONNULL_BEGIN

#pragma mark - Device Info's key
extern NSString *const HS2SProDeviceInfoKeyProtocol;
extern NSString *const HS2SProDeviceInfoKeySerialNumber;
extern NSString *const HS2SProDeviceInfoKeyName;
extern NSString *const HS2SProDeviceInfoKeyFirmwareVersion;
extern NSString *const HS2SProDeviceInfoKeyHardwareVersion;
extern NSString *const HS2SProDeviceInfoKeyManufacture;
extern NSString *const HS2SProDeviceInfoKeyModelNumber;
extern NSString *const HS2SProDeviceInfoKeyBattery;
extern NSString *const HS2SProDeviceInfoKeyUserCount;
extern NSString *const HS2SProDeviceInfoKeyUnit;

extern NSString *const HS2SProResultInfoKeySuccessFlag;
extern NSString *const HS2SProResultInfoKeyMAC;
extern NSString *const HS2SProResultInfoKeyResult;

typedef NS_ENUM(uint8_t,HS2SProGender) {
    HS2SProGender_Female = 0,
    HS2SProGender_Male = 1,
};

typedef NS_ENUM(uint8_t, HS2SProBLEBoardcastParameter) {
    HS2SProBLEBoardcastParameter_NotBoardcast=0x00,
    HS2SProBLEBoardcastParameter_Slow=0x01,//546.25ms
    HS2SProBLEBoardcastParameter_Slowest=0x02,//1022.5ms
};

typedef NS_ENUM(NSInteger, HS2SProImpedanceMeasureErrorCode) {
    HS2SProImpedanceMeasureErrorCode_Success,
    HS2SProImpedanceMeasureErrorCode_Error1,
    HS2SProImpedanceMeasureErrorCode_Error2,
    HS2SProImpedanceMeasureErrorCode_Error3,
    HS2SProImpedanceMeasureErrorCode_Error4,
    HS2SProImpedanceMeasureErrorCode_Error5,
};


@interface HS2SProUser : NSObject
/// 16 bytes, genernal used md5 method: NSString -> NSData
@property (copy, nonatomic) NSData *userId;

/// Timestamp create or update user information
@property (assign, nonatomic) uint32_t createTS;

/// Gender
@property (assign, nonatomic) HS2SProGender gender;
/// 0-99 years
@property (assign, nonatomic) uint8_t age;

/// 50-255cm
@property (assign, nonatomic) uint8_t height;

/// 5-180kg
@property (assign, nonatomic) double weight;

/// If enable measure body fat
@property (assign, nonatomic) BOOL enableMeasureImpedance;

/// If user is doing exercise fitness
@property (assign, nonatomic) BOOL enableFitness;
@end

@interface HS2SProMeasurementModel : NSObject
/// generated by sdk not by device
@property (copy, nonatomic) NSString *dataId;
/// weight
@property (assign, nonatomic) double weight;
/// impedance value
@property (assign, nonatomic) uint16_t impedance1;
/// impedance value
@property (assign, nonatomic) uint16_t impedance2;
/// impedance value
@property (assign, nonatomic) uint16_t impedance3;
/// impedance value
@property (assign, nonatomic) uint16_t impedance4;
/// Gender
@property (assign, nonatomic) HS2SProGender gender;
/// user's age
@property (assign, nonatomic) uint8_t age;
/// user's height
@property (assign, nonatomic) uint8_t height;
/// measure time
@property (copy, nonatomic) NSDate *measureTS;
/// Before sync time with device, the isRightTime is NO, So you should call commandGetHS2SPRODeviceInfo api to make sure offline data's measureTS is right
@property (assign, nonatomic) BOOL isRightTime;
/// fitness flag
@property (assign, nonatomic) BOOL enableFitness;
/// Error Code
@property (assign, nonatomic) HS2SProImpedanceMeasureErrorCode impedanceMeasureErrorCode;
/// 5.0~60.0 %
@property (assign, nonatomic) double bodyFatPercentage;
/// 10.0~120.0 kg
@property (assign, nonatomic) double muscle;
/// 0.5~8.0 kg
@property (assign, nonatomic) double boneMineral;
/// 35.0~75.0%
@property (assign, nonatomic) double bodyWaterPercentage;
/// 2.0~30.0%
@property (assign, nonatomic) double proteinPercentage;
/// 1~50
@property (assign, nonatomic) int8_t vfr;
/// 6~99
@property (assign, nonatomic) int8_t bodyAge;
/// BMI
@property (assign, nonatomic) double bmi;
/// 500~10000 Kcal
@property (assign, nonatomic) double bmr;
/// leanWeight = weight*(1-bodyFatPercentage)
@property (assign, nonatomic) double leanWeight;
///encrypt Impedance
@property (assign, nonatomic) uint32_t encryptImpedance;
///login Id
@property (assign, nonatomic) uint8_t loginId;

@end

@interface HS2SProAnonymousModel : NSObject
/// generate by sdk not by device
@property (copy, nonatomic) NSString *dataId;
/// weight
@property (assign, nonatomic) double weight;
/// measure time
@property (copy, nonatomic) NSDate *measureTS;
/// Before sync time with device, the isRightTime is NO, So you should call commandGetHS2SPRODeviceInfo api to make sure offline data's measureTS is right
@property (assign, nonatomic) BOOL isRightTime;
@end

#pragma mark - HS2S PRO Block

typedef void (^DisposeHS2SPROResult)(void);
typedef void (^DisposeHS2SPROErrorBlock)(HS2SPRODeviceError errorID);
typedef void (^DisposeHS2SPRODeviceInfo)(NSDictionary*deviceInfo);
typedef void (^DisposeHS2SPROBatteryBlock)(NSNumber *battary);
typedef void (^DisposeHS2SPROUserInfo)(NSArray<HS2SProUser*> *array);

typedef void (^DisposeHS2SPROUnStableWeight)(NSNumber *unStableWeight);
typedef void (^DisposeHS2SPROStableWeight)(NSNumber *stableWeight);
typedef void (^DisposeHS2SPROWeightAndBodyInfo)(NSDictionary *weightAndBodyInfoDic);

typedef void (^DisposeHS2SPROMemoryCountBlock)(NSNumber *count);
typedef void (^DisposeHS2SPROMemoryDataBlock)(NSArray<HS2SProMeasurementModel*> *data);
typedef void (^DisposeHS2SPROAnonymousMemoryCountBlock)(NSNumber *count);
typedef void (^DisposeHS2SPROAnonymousMemoryDataBlock)(NSArray<HS2SProAnonymousModel*> *data);

typedef void (^DisposeHS2SPROMeasurementStatus)(NSNumber *measurementStatus);
typedef void (^DisposeHS2SPROHeartResult)(NSDictionary *heartResultDic);

@class HS2SProInternal;
@interface HS2SPRO : NSObject

/// Use MAC Address as serial Number
@property (strong, nonatomic) NSString *serialNumber;

/// UUID assigned by iOS System
@property (strong, nonatomic) NSString *currentUUID;

@property (assign, nonatomic) HSUnit unit;

@property (nonatomic,strong) HS2SProInternal *hs2sPROBasicDevice;

/// Sync time with device and get device information
/// @param successBlock success callback, dictionary key see Device Info's key
/// @param disposeErrorBlock error callback
-(void)commandGetHS2SPRODeviceInfo:(DisposeHS2SPRODeviceInfo)successBlock
                 disposeErrorBlock:(DisposeHS2SPROErrorBlock)disposeErrorBlock;

/// Get device's battery
/// @param successBlock success callback, battery range 0~100
/// @param disposeErrorBlock error callback
-(void)commandGetHS2SPROBattery:(DisposeHS2SPROBatteryBlock)successBlock
              disposeErrorBlock:(DisposeHS2SPROErrorBlock)disposeErrorBlock;

/// Set weight unit displayed on device's screen
/// @param unit See HSUnit
/// @param successBlock success callback
/// @param disposeErrorBlock error callback
-(void)commandSetHS2SPROUnit:(HSUnit)unit
                successBlock:(DisposeHS2SPROResult)successBlock
           disposeErrorBlock:(DisposeHS2SPROErrorBlock)disposeErrorBlock;

/// Get user info list created in device
/// @param successBlock success callback, see HS2SProUser
/// @param disposeErrorBlock error callback
-(void)commandGetHS2SPROUserInfo:(DisposeHS2SPROUserInfo)successBlock
               disposeErrorBlock:(DisposeHS2SPROErrorBlock)disposeErrorBlock;


/// Create or update user info in device (Only support create <= 8 users in device)
/// @param user see HS2SProUser
/// @param successBlock success callback
/// @param disposeErrorBlock error callback
-(void)commandUpdateHS2SPROUserInfoWithUser:(HS2SProUser*)user
                               successBlock:(DisposeHS2SPROResult)successBlock
                          disposeErrorBlock:(DisposeHS2SPROErrorBlock)disposeErrorBlock;

/// Delete an user in device
/// @param userId user's identifier, see HS2SProUser
/// @param successBlock success callback
/// @param disposeErrorBlock error callback
-(void)commandDeleteHS2SPROUserWithUserId:(NSData*)userId
                             successBlock:(DisposeHS2SPROResult)successBlock
                        disposeErrorBlock:(DisposeHS2SPROErrorBlock)disposeErrorBlock;

/// Get the number of measurements stored in device with the specific user
/// @param userId user's identifier, see HS2SProUser
/// @param successBlock success callback, range: 0~500
/// @param disposeErrorBlock error callback
-(void)commandGetHS2SPROMemoryDataCountWithUserId:(NSData*)userId
                                     successBlock:(DisposeHS2SPROMemoryCountBlock)successBlock
                                disposeErrorBlock:(DisposeHS2SPROErrorBlock)disposeErrorBlock;

/// Get the measurements sotred in device with the specific user
/// @param userId user's identifier, see HS2SProUser
/// @param successBlock success callback, see HS2SProMeasurementModel
/// @param disposeErrorBlock error callback
-(void)commandGetHS2SPROMemoryDataWithUserId:(NSData*)userId
                                successBlock:(DisposeHS2SPROMemoryDataBlock)successBlock
                           disposeErrorBlock:(DisposeHS2SPROErrorBlock)disposeErrorBlock;

/// Delete all measurements sotred in device with the specific user
/// @param userId user's identifier, see HS2SProUser
/// @param successBlock success callback
/// @param disposeErrorBlock error callback
-(void)commandDeleteHS2SPROMemoryDataWithUserId:(NSData*)userId
                                   successBlock:(DisposeHS2SPROResult)successBlock
                              disposeErrorBlock:(DisposeHS2SPROErrorBlock)disposeErrorBlock;

/// Get the number of measurements stored in device which not belong to any user
/// @param successBlock success callabck
/// @param disposeErrorBlock error callback
-(void)commandGetHS2SPROAnonymousMemoryDataCount:(DisposeHS2SPROAnonymousMemoryCountBlock)successBlock
                               disposeErrorBlock:(DisposeHS2SPROErrorBlock)disposeErrorBlock;

/// Get the measurements sotred in device which not belong to any user
/// @param successBlock success callback, see HS2SProAnonymousModel
/// @param disposeErrorBlock error callback
-(void)commandGetHS2SPROAnonymousMemoryData:(DisposeHS2SPROAnonymousMemoryDataBlock)successBlock
                          disposeErrorBlock:(DisposeHS2SPROErrorBlock)disposeErrorBlock;

/// Delete all measurements sotred in device which not belong to any user
/// @param successBlock success callback
/// @param disposeErrorBlock error callback
-(void)commandDeleteHS2SPROAnonymousMemoryData:(DisposeHS2SPROResult)successBlock
                             disposeErrorBlock:(DisposeHS2SPROErrorBlock)disposeErrorBlock;

///  Start measure with specific user info
/// @param user see HS2SProUser
/// @param realtimeWeightBlock the value means  changing weight value before the device gets a stable value. unit: kg
/// @param stableWeightBlock a stable weight value
/// @param weightAndBodyInfoBlock complete body info result, including body fat percentage and so on. Example:
///{
/// MAC = 3CAA408E0002;
/// Result = "<HS2SProMeasurementModel: 0x283069700>";
/// SuccessFlag = 0; // 0: success 1: fail, not get impedance 2: fail, not compute body fat and other results successfully
/// }
/// @param disposeErrorBlock error callabck
-(void)commandStartHS2SPROMeasureWithUser:(HS2SProUser*)user
                      realtimeWeightBlock:(DisposeHS2SPROUnStableWeight)realtimeWeightBlock
                        stableWeightBlock:(DisposeHS2SPROStableWeight)stableWeightBlock
                   weightAndBodyInfoBlock:(DisposeHS2SPROWeightAndBodyInfo)weightAndBodyInfoBlock
                        disposeErrorBlock:(DisposeHS2SPROErrorBlock)disposeErrorBlock;


/// Start guest Measure ( Only measure Weight). Warninig: You should call commandStartHS2SPROMeasureWithUser: api to restart a normal measure process.
/// @param realtimeWeightBlock the value means  changing weight value before the device gets a stable value. unit: kg
/// @param stableWeightBlock a stable weight value
/// @param disposeErrorBlock error callabck
- (void)commandStartHS2SPROGuestMeasureWithRealtimeWeightBlock:(DisposeHS2SPROUnStableWeight)realtimeWeightBlock
                                             stableWeightBlock:(DisposeHS2SPROStableWeight)stableWeightBlock
                                             disposeErrorBlock:(DisposeHS2SPROErrorBlock)disposeErrorBlock;


/// Reset device. All users and data will be removed and the settings will be reset.
/// @param successBlock success callback
/// @param disposeErrorBlock error callback
-(void)commandResetHS2SPRODevice:(DisposeHS2SPROResult)successBlock
               disposeErrorBlock:(DisposeHS2SPROErrorBlock)disposeErrorBlock;

/// Set Bluetooth Boardcast type. You can use this api to change battery cost speed.
/// @param type sett HS2SProBLEBoardcastParameter
/// @param successBlock success callback
/// @param disposeErrorBlock error callback
- (void)commandSetHS2SPROBLEBoardcast:(HS2SProBLEBoardcastParameter)type
                         successBlock:(DisposeHS2SPROResult)successBlock
                    disposeErrorBlock:(DisposeHS2SPROErrorBlock)disposeErrorBlock;

/// Active disconnect a device from app
- (void)commandDisconnectDevice;

/// Show bluetooth symbol in device's screen.
/// @param successBlock success callback
/// @param disposeErrorBlock error callback
-(void)commandShowBluetoothLightWithSuccessBlock:(DisposeHS2SPROResult)successBlock
                        disposeErrorBlock:(DisposeHS2SPROErrorBlock)disposeErrorBlock;


/// Enter heart rate measurement mode
/// @param result example:
/// heartResultDic:
/// {
///     HS2SProNotiKeyHeartRate = 89;
///     HS2SProNotiKey_MeasureSuccessFlag = 0; // no error
///     MAC = 3CAA408E0005;
/// }
/// {
///     HS2SProNotiKey_MeasureSuccessFlag" = 1; // error 1: no real-time data received in 6s, 2:  the algorithm judges that the user is weighing down,3:  calculation failed,4: 30s timeout
///     MAC = 3CAA408E0005;
/// }
/// @param status ( 1: User on the scale,2: User referred below,3: The user's heartbeat signal is detected)
/// @param disposeErrorBlock error callback
-(void)commandEnterHS2SPROHeartRateMeasurementMode:(DisposeHS2SPROHeartResult)result
                                 measurementStatus:(DisposeHS2SPROMeasurementStatus)status
                                 disposeErrorBlock:(DisposeHS2SPROErrorBlock)disposeErrorBlock;


/// Exit heart rate measurement mode.
/// @param result success callback
/// @param disposeErrorBlock error callback
-(void)commandExitHS2SPROHeartRateMeasurementMode:(DisposeHS2SPROResult)result disposeErrorBlock:(DisposeHS2SPROErrorBlock)disposeErrorBlock;

@end

NS_ASSUME_NONNULL_END
