//
//  MicroLifeDevice.h
//  MicroLifeDeviceSDK
// 1. Compilation tool
// 2. Encryption and decryption tools
// 3. Verification tool
// 4. Compile instructions for each device (rewrite for each device)
//  Created by willy.wu on 2020/11/18.
//

#import <Foundation/Foundation.h>
#import <MicroLifeDeviceSDK/BLEDeviceInfo.h>
#import <MicroLifeDeviceSDK/MicroLifeDataModel.h>

NS_ASSUME_NONNULL_BEGIN

typedef void(^deviceConnectedBlock) (void);

typedef void(^readDataValueBlock) (NSInteger CMD, NSData * value, NSError * error);

typedef void(^readDataModelBlock) (NSInteger CMD, id model, NSError * error);

typedef void(^validationErrorBlock) (NSString *item, NSString *info, id value);

typedef void(^pairingErrorBlock) (NSError * error);

@interface MicroLifeDevice : NSObject

@property (nonatomic, strong) NSDateComponents *dateComponents;

/// DeviceModel
@property (nonatomic, strong) NSMutableArray *deviceModels;

/// DeviceInfo
@property (nonatomic, strong) BLEDeviceInfo *deviceInfo;

/// name
@property (nonatomic, strong) NSString *name;

/// UUID
@property (nonatomic, strong) NSString *UUID;

/// Mac Address
@property (nonatomic, strong) NSData *mac;

/// RSSI
@property (nonatomic, strong) NSNumber *RSSI;

/// DeviceType
@property (nonatomic, assign) MicroLifeDeviceType deviceType;

/// DeviceConnected
@property (nonatomic, assign) BOOL deviceConnected;

/// AutoConnect
@property (nonatomic, assign) BOOL isAutoConnect;

/// reConnectIndex
@property (nonatomic, assign) NSInteger reConnectIndex;

/// reply NACK.
@property (nonatomic, assign) BOOL replyACK;

/// reply NullACK.
@property (nonatomic, assign) BOOL replyNullACK;

/// offset Year
@property (nonatomic, assign) NSInteger offsetYear;

/// protocol Version
@property (nonatomic, assign) NSInteger protocolID;

/// bt_code
@property (nonatomic, assign) NSInteger bt_code;

@property (nonatomic, strong) NSNumber *writeCMD;

@property (nonatomic, strong) NSString *deviceHeader;

/// share
/// @param key Key
+ (instancetype)shareWhithAuthorizationkey:(NSString *)key;

/// share
/// @param code code
/// @param key key
/// @param secret secret
+ (instancetype)shareWhithAuthorization:(NSString *)code Key:(NSString *)key Secret:(NSString *)secret;

/// Create custom bluetooth manager 創建自定義藍牙管理器
///
/// This method allows developers to replace the default BLESDK with their own bluetooth manager implementation. 此方法允許開發者用自己的藍牙管理器實現來替換默認的 BLESDK
///
/// The custom bluetooth manager must implement BluetoothManagerProtocol to ensure compatibility. 自定義藍牙管理器必須實現 BluetoothManagerProtocol 以確保兼容性
///
/// @param manager The custom bluetooth manager that implements BluetoothManagerProtocol 實現了 BluetoothManagerProtocol 的自定義藍牙管理器
///
/// Usage example 使用示例:
/// @code
/// // Create custom manager 創建自定義管理器
/// id<BluetoothManagerProtocol> customManager = [CustomBLESDK shared];
///
/// // Set custom manager 設置自定義管理器
/// [device setBLEManager:customManager];
/// @endcode
///
/// @note The custom manager must implement all required methods in BluetoothManagerProtocol
///       自定義管理器必須實現 BluetoothManagerProtocol 中的所有必要方法
///
/// @warning Replacing the bluetooth manager while device is connected may cause unexpected behavior
///          在設備連接時替換藍牙管理器可能會導致意外行為
- (void)setBLEManager:(id<BluetoothManagerProtocol>)manager;

/// add Device Model
/// @param models models
- (void)addDeviceModel:(NSArray *)models;

/// add Device Model
/// @param models models
- (void)addDeviceModel:(NSArray *)models RemoveAll:(BOOL)removeAll;

/// Auto Connect [Default: Open]
/// @param autoConnect autoConnect 
- (void)autoConnect:(BOOL)autoConnect;

/// ReConnect Time  [Default: 0]
/// @param reConnectIndex reConnectIndex
- (void)reConnectTime:(NSInteger)reConnectIndex;

/// Set Sacn stop Time
/// @param time time
- (void)stopTime:(NSInteger)time;

/// Set RSSI
/// @param rssi RSSI
- (void)rssi:(NSInteger)rssi;

/// When CBManagerStatePoweredOn automatically opens scanning [Default: Open]
/// @param autoScan autoScan
- (void)autoScan:(BOOL)autoScan;

/// Set Device Info
/// @param deviceInfo deviceInfo
- (BOOL)deviceInfo:(id)deviceInfo;

/// Start Sacn
- (void)startScan;

/// Cancel Scan
- (void)cancelScan;

/// Connect
- (void)connectDevice;

/// Disconnect
- (void)disconnectDevice;

/// Set Auto Reconnect
- (void)setAutoReconnect;

/// Cancel Auto Reconnect
- (void)cancelAutoReconnect;

/// Device Connected
/// @param block deviceConnectedBlock
- (void)deviceConnectedBlock:(deviceConnectedBlock)block;

/// Device independent bluetooth
/// @param didUpdateStateBlock didUpdateStateBlock
/// @param scanDeviceBlock scanDeviceBlock
/// @param cancelScanBlock cancelScanBlock
/// @param connectDeviceStateBlock connectDeviceStateBlock
/// @param cancelAllDevicesConnectionBlock cancelAllDevicesConnectionBlock
- (void)getDidUpdateStateBlock:(didUpdateStateBlock)didUpdateStateBlock ScanDeviceBlock:(scanDeviceBlock)scanDeviceBlock CancelScanBlock:(cancelScanBlock)cancelScanBlock ConnectDeviceStateBlock:(connectDeviceStateBlock)connectDeviceStateBlock CancelAllDevicesConnectionBlock:(cancelAllDevicesConnectionBlock)cancelAllDevicesConnectionBlock;

/// Read RSSI
/// @param block readRSSIBlock
- (void)getReadRSSIBlock:(readRSSIBlock)block;

/// Read Data Value
/// @param block readDataValueBlock
- (void)getReadDataValueBlock:(readDataValueBlock)block;

/// Read Data Model
/// @param block readDataModelBlock
- (void)getReadDataModelBlock:(readDataModelBlock)block;

/// Read Valify item Error
/// @param block validationErrorBlock
- (void)getValidationErrorBlock:(validationErrorBlock)block;

/// Read Pairing item Error
/// @param block pairingErrorBlock:
/// error.code 14 Device pairing cleared
/// error.code 15 Clear mobile phone pairing
- (void)getPairingErrorBlock:(pairingErrorBlock)block;

#pragma amrk
/// Start ScheduledTimer
- (void)startScheduledTimer;

/// Cancel ScheduledTimer
- (void)cancelScheduledTimer;

/// Cancel Write Value
- (void)cancelWriteValue;

/// Write Value
/// @param replyCMDValue replyCMDValue
/// @param value value
/// @param checkCMD checkCMD
/// @param checkCMDValue checkCMDValue
/// @param notRespond notRespond
/// @param mergeValue mergeValue
- (void)writeCMD:(NSInteger)replyCMDValue Value:(NSString *)value CheckCMD:(BOOL)checkCMD CheckCMDValue:(NSInteger)checkCMDValue NotRespond:(BOOL)notRespond MergeValue:(BOOL)mergeValue;

/// write Priority Value
/// @param replyCMDValue replyCMDValue
/// @param value value
/// @param checkCMD checkCMD
/// @param checkCMDValue checkCMDValue
/// @param notRespond notRespond
/// @param mergeValue mergeValue
- (void)writePriorityCMD:(NSInteger)replyCMDValue Value:(NSString *)value CheckCMD:(BOOL)checkCMD CheckCMDValue:(NSInteger)checkCMDValue NotRespond:(BOOL)notRespond MergeValue:(BOOL)mergeValue;

/// HEARTCHECK
/// @param value HEART Value
/// @param interval HEART Interval
- (void)HEARTCHECK:(NSString *)value WithTimeInterval:(NSInteger)interval;

/// afterWork
/// @param interval time sec
/// @param block block
- (void)afterWork:(NSInteger)interval block:(dispatch_block_t)block;

/// Check LastWork
/// @param time time
- (BOOL)checkLastWork:(NSInteger)time;

/// Update Notification State For Characteristic
/// @param block updateNotificationStateForCharacteristicBlock
- (void)getUpdateNotificationStateForCharacteristicBlock:(updateNotificationStateForCharacteristicBlock)block;

/// Sync Time
- (void)syncTime;

#pragma mark - For device state, can be overridden
/// Connect Device State to work
/// @param peripheral CBPeripheral
/// @param error NSError
- (void)connectDeviceStateToWork:(CBPeripheral *)peripheral Error:(NSError *)error;

/// Device State To Work
/// @param state CBPeripheralState
/// @param error NSError
- (void)discoverCharacteristicsToWork:(CBPeripheralState)state Error:(NSError *)error;

/// Parse bluetooth raw data
/// @param CMD CMD
/// @param data data
/// @param value Raw data
- (id)analysisCMD:(NSInteger)CMD Data:(NSString *)data Value:(NSData *)value;

/// Parse broadcast data
/// @param advertisementData broadcast data
- (id)analysisBroadcastData:(NSDictionary *)advertisementData;

#pragma mark - Build WriteValue , can be overridden
/// Merge Value Index
- (NSInteger)mergeValueIndex;

/// Merge Value
/// @param value value
/// @param data data
- (NSMutableData *)mergeValue:(NSData *)value Data:(NSData *)data;

/// lengthSize
/// @param data data
- (NSString *)lengthSize:(NSString *)data;

/// computation CheckSum
/// @param value value
- (NSString *)computationCheckSum:(NSString *)value;

/// encryption Value
/// @param value value
- (NSString *)encryptionValue:(NSString *)value;

/// compile Data
/// @param compileData compileData description
/// @param length length description
/// @param aString aString description
- (NSString *)compileData:(NSString *)compileData CompileLength:(NSInteger)length AppendingString:(NSString *)aString;

/// replenish Data
/// @param replenishData replenishData
/// @param length length
/// @param aString aString
- (NSString *)replenishData:(NSString *)replenishData ReplenishLength:(NSInteger)length AppendingString:(NSString *)aString;

/// build Write Value data = firstData+compileData+lastData
/// @param CMD CMD
/// @param firstData firstData
/// @param compileData compileData
/// @param length length
/// @param aString aString
/// @param lastData lastData
- (NSString *)buildwriteValueCMD:(NSInteger)CMD FirstData:(NSString *)firstData CompileData:(NSString *)compileData CompileLength:(NSInteger)length AppendingString:(NSString *)aString LastData:(NSString *)lastData;

/// build Write Value data = firstData+replenishData+lastData
/// @param CMD CMD
/// @param firstData firstData
/// @param replenishData replenishData
/// @param length length
/// @param aString aString
/// @param lastData lastData
- (NSString *)buildwriteValueCMD:(NSInteger)CMD FirstData:(NSString *)firstData ReplenishData:(NSString *)replenishData ReplenishLength:(NSInteger)length AppendingString:(NSString *)aString LastData:(NSString *)lastData;

#pragma mark - CMD - Compile instructions for each device (rewrite for each device)

@end

NS_ASSUME_NONNULL_END
