//
//  RTKDFUPeripheral.h
//  RTKOTASDK
//
//  Created by jerome_gu on 2019/4/16.
//  Copyright © 2019 Realtek. All rights reserved.
//

#ifdef RTK_SDK_IS_STATIC_LIBRARY
#import "libRTKLEFoundation.h"
#import "RTKOTAPeripheral.h"
#import "RTKOTAUpgradeBin.h"
#else
#import <RTKLEFoundation/RTKLEFoundation.h>
#import <RTKOTASDK/RTKOTAPeripheral.h>
#import <RTKOTASDK/RTKOTAUpgradeBin.h>
#endif


/*!
 * Values represents the phase during upgrade.
 */
typedef enum : NSUInteger {
    RTKDFUPhaseNone, ///< The peripheral is not upgrading currently.
    RTKDFUPhaseSending, ///< The peripheral is receiving image bytes.
    RTKDFUPhaseActivating, ///< The peripheral activating images received.
    RTKDFUPhaseResetting, ///< The peripehral is resetting. Usual happened after encounter an upgrade error.
    RTKDFUPhaseCanceling, ///< The peripheral is canceling upgrade.
    RTKDFUPhaseReconnecting, ///< App is reconnecting to peripheral in order to send more images.
    RTKDFUPhaseEncounterError, ///< Upgrade is broken down for error encountered.
} RTKDFUPhase;


NS_ASSUME_NONNULL_BEGIN


@class RTKDFUPeripheral;

/**
 * @protocol RTKDFUPeripheralDelegate
 *
 * RTKDFUPeripheralDelegate define several addition methods for repoert upgrade update event.
 */
@protocol RTKDFUPeripheralDelegate <RTKLEPeripheralDelegate>
@required

/**
 * Tell the delegate that OTA upgrade did complete.
 *
 * @param err  The reason the call failed, or nil if no error occurred.
 */
- (void)DFUPeripheral:(RTKDFUPeripheral *)peripheral didFinishWithError:(nullable NSError *)err;

@optional

/**
 * Tell the delegate that the sending progress did changed.
 */
- (void)DFUPeripheral:(RTKDFUPeripheral *)peripheral didSend:(NSUInteger)length totalToSend:(NSUInteger)totalLength;

/**
 * Ask the delegate for if to active image when finish send image bytes.
 *
 *@discussion When return NO, you should call -sendActiveResetToNormalMessage manually to complete upgrade procedure, otherwise the behaviour is not defined.
 */
- (BOOL)DFUPeripheralShouldActiveImageWhenCompleteSend:(RTKDFUPeripheral *)peripheral;

- (BOOL)DFUPeripheral:(RTKDFUPeripheral *)peripheral shouldWaitForDisconnectionOnCompleteSend:(RTKOTAUpgradeBin *)image DEPRECATED_MSG_ATTRIBUTE("use -DFUPeripheralShouldWaitForDisconnectionAfterActiveImage: instead");

/**
 * Ask the delegate if to wait for LE disconnection with the device before call -DFUPeripheral:didFinishWithError: method.
 *
 * @discussion Delegate should return NO if want -DFUPeripheral:didFinishWithError: method get called immediately after active image. default is YES
 */
- (BOOL)DFUPeripheralShouldWaitForDisconnectionAfterActiveImage:(RTKDFUPeripheral *)peripheral;

@end



@class RTKOTAProfile;

/*!
 * @class RTKDFUPeirpheral
 * A remote device with interfaces for firmware upgrade.
 *
 * @discussion
 * The RTKDFUPeirpheral class defines some programatic intefaces for app to control firmware upgrade. Instead of create a RTKDFUPeripheral object manually, it's better to retrieve a instance by call RTKOTAProfile methods. Before you can call any upgrade control methods (e.g. -upgradeImage:), the RTKDFUPeripheral @b should be connected by RTKOTAProfile. When upgrade get started, it will call RTKDFUPeripheralDelegate protocol methods on delegate to report progress and completion event.
 *
 * @see RTKOTAPeripheral
 */
@interface RTKDFUPeripheral : RTKLEPeripheral {
    @protected
    RTKDFUPhase _phase;
    RTKOTAUpgradeBin *_upgradingImage;
}

/**
 * The delegate object specified to receive upgrade events.
 */
@property (nonatomic, weak) id <RTKDFUPeripheralDelegate> delegate;

/**
 * Return a RTKOTAPeripheral object which has APIs exposes OTA related information of the remote device.
 */
@property (nonatomic, readonly) RTKOTAPeripheral *OTAPeripheral;

/**
 * The current phase of upgrade task.
 */
@property (nonatomic, readonly) RTKDFUPhase phase;

/**
 * The image which peripheral is upgrading currently.
 *
 * @discussion Return nil if upgrade is not in progress.
 */
@property (readonly, nullable) RTKOTAUpgradeBin *upgradingImage;

/**
 * Set key for encryption when upgrade.
 *
 * @discussion If not set, a default key is used.
 */
- (void)setEncryptKey:(NSData * _Nonnull)encryptKey;


- (instancetype)initWithCBPeripheral:(CBPeripheral *)peripheral OTAPeripheral:(nullable RTKOTAPeripheral *)OTAPeri profile:(RTKOTAProfile *)profile;

/**
 * Start firmware upgrade with a image object.
 */
- (void)upgradeImage:(RTKOTAUpgradeBin *)image;

/**
 * Cancel ongoing upgrade.
 *
 * @warning Not support currently.
 */
- (void)cancelUpgrade;

/**
 * Set to change the retry number on buffer check fail.
 *
 * @discussion Default value is 2.
 */
@property (nonatomic) NSUInteger retryCountWhenBufferCheckFail;

/**
 * Set Channel Connection Parameters.
 *
 * @discussion Unit: ms
 */
-(void)setConnectionParametersWithMinInterval:(uint16_t)intervalMin maxInterval:(uint16_t)intervalMax latency:(uint16_t)latency supervisionTimeout:(uint16_t)timeout;


/**
 * Used in a particular case.
 */
- (void)sendActiveResetToNormalMessage;

@end

NS_ASSUME_NONNULL_END