//
//  GHDevice.h
//  Garmin Health
//
//  Created by Timar, Mihai on 22/07/15.
//  Copyright © 2016 Garmin International, Inc. or its affiliates. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "GHScannedDevice.h"
#import "GHDeviceSettings.h"
#import "GHDeviceTypes.h"
#import "GHFirmwareResult.h"


extern NSString * const GHBatteryStatusErrorDomain;
extern NSString * const GHLoggingStateErrorDomain;
extern NSString * const GHConnectIQLaunchErrorDomain;


/**
 *  Enum of possible connection status states.
 */
typedef NS_ENUM(NSInteger, GHConnectionStatus) {
    /**
     * Device is not connected.
     */
    GHConnectionStatusNotConnected = 0,
    /**
     *  Device is connected and can receive/send messages.
     */
    GHConnectionStatusConnected = 1
};


/**
 *  Enum of possible battery status error codes.
 */
typedef NS_ENUM(NSInteger, GHBatteryStatusError) {
    /**
     * Device is not connected.
     */
    GHBatteryStatusErrorNotConnected = 0,
    /**
     *  Device is connected but a valid read cannot be obtained
     */
    GHBatteryStatusErrorCannotRead = 1,
    /**
     *  Device is connected, but does not support on demand battery information
     */
    GHBatteryStatusErrorNotAvailable = 2
};


/**
 *  Enum of Connect IQ launch status codes.
 */
typedef NS_ENUM(NSInteger, GHLaunchConnectIQAppStatus) {
    /**
     *  Connect IQ App was launched successfully.
     */
    GHLaunchConnectIQAppStatusSuccess = 0,
    /**
     * Connect IQ App was already running.
     */
    GHLaunchConnectIQAppStatusAlreadyRunning = 1,
    /**
     *  Connect IQ App is not installed.
     */
    GHLaunchConnectIQAppStatusNotInstalled = 2,
    /**
     *  Device is not connected.
     */
    GHLaunchConnectIQAppStatusNotConnected = 3,
    /**
     *  An unknown error occured.
     */
    GHLaunchConnectIQAppStatusUnknown = 4,
    /**
     *  Connect IQ App Launch is not supported on this device.
     */
    GHLaunchConnectIQAppStatusNotSupported = 5
};


#pragma mark - 
/**
 *  Type definition for Block.
 */
typedef void (^GHFirmwareUpdateResult)(GHFirmwareResult *result, GHFirmwareStatus status);

/**
 *  Type definition for Block.
 */
typedef void (^GHBatteryStatusResult)(int percent, NSError* error);

/**
 *  Type definition for Block.
 */
typedef void (^GHConnectIQAppResult)(GHLaunchConnectIQAppStatus status, NSError* error);


#pragma mark -
/**
 *  Information about a scanned Garmin device.
 */
@interface GHDevice : GHScannedDevice <NSCoding>

/** Whether device is connected. Refer to GHConnectionStatus for additional information. */
@property (nonatomic, readonly) GHConnectionStatus status;

/** Number of queued updates for this device */
@property (nonatomic, readonly) unsigned pendingUpdates;

/** Whether the device supports manually requesting sync from your app */
@property (nonatomic, readonly) BOOL supportsManualSync;

/**  Array of GHLanguage objects supported by the device. Refer to GHLanguage for additional information. */
@property (nonatomic, readonly) NSArray<GHLanguage *>* supportedLanguages;

/**
 *  Settings currently on device or those that will be sent to the device during next sync.
 *  Updated with the updateSettings:error: method.
 */
@property (nonatomic, readonly) GHDeviceSettings* settings;

/**
 *  The Unit ID of the device.
 */
@property (nonatomic, readwrite) NSNumber *unitID;

/**
 * The device firmware version as an integer.
 * Follows the form XXX -> X.XX (i.e. 370 -> 3.70)
 */
@property (nonatomic, readonly) NSNumber *softwareVersion;


#pragma mark - Methods
/**
 *  Attempts to launch a Connect IQ app.
 *  @param uuid NSUUID associated with the app.
 *  @param completionHandler GHConnectIQAppResult block that is called with the results of the call.
 */
- (void)launchConnectIQAppWithUUID:(NSUUID *)uuid completion:(GHConnectIQAppResult)completionHandler;

/**
 *  Provide updated settings to be sent on the next sync. Will return validation
 *  errors and not save/send if required fields are not set.
 *  @param settings GHDeviceSettings to send to the device.
 *  @param error Error reported if one occured.
*/
- (void)updateSettings:(GHDeviceSettings *)settings error:(NSError **)error;

/**
 *  Checks for firmware updates for the device.
 *  @param completionHandler GHFirmwareUpdateResult block that is called
 *  when the firmware check is completed. If multiple files are availalble this
 *  callback will be notified multiple times.
 */
- (void)checkForFirmwareUpdate:(GHFirmwareUpdateResult)completionHandler;

/**
 *  Queues the firmware update for download to the device during the next sync.
 *  @param firmware GHFirmwareResult the firware result to be loaded onto the Garmin device.
 *  @note call checkForFirmwareUpdate before calling this method.
 */
- (void)queueFirmwareUpdate:(GHFirmwareResult *)firmware;

/**
 *  Queue a request for sync. Device must support the request and be ready for a sync.
 *  @note A device might decide to ignore the request. If a sync doesn't initiate in 30s from the request, it was ignored. 
 *  @return YES if the request was queued. NO if the device is not connected or doesn't support such requests.
 */
- (BOOL)requestSync;

/**
 *  Checks battery status on device.
 *  @note Only select devices will actually return useful data.
 *  @param completion GHBatteryStatusResult block containing response from device or error
 */
- (void)requestBatteryStatus:(GHBatteryStatusResult)completion;


/** NS_UNAVAILABLE */
+ (instancetype)new NS_UNAVAILABLE;

/** NS_UNAVAILABLE */
- (instancetype)init NS_UNAVAILABLE;

@end
