//
// © 2018-2020 Qualcomm Technologies, Inc. and/or its subsidiaries. All rights reserved.
//

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

NS_ASSUME_NONNULL_BEGIN

/**
 @brief Representation of a device password.
 @discussion A device password may be requested from the user to perform certain actions. The API requires either a password (with cancel false) or the cancelled state (cancel = true).
 */
@interface IoTDevicePassword : NSObject
@property (nonatomic, readonly) BOOL cancel;
@property (nonatomic, readonly, nullable) NSString *password;

- (instancetype)initWithCancel:(BOOL)cancel password:(nullable NSString *)password;

@end

#pragma mark -

/**
 @brief Denotes the type of a Voice UI service that may be available
 */
typedef NS_ENUM(NSInteger, IoTVoiceUIClientType) {
    /** Unknown */
    IoTVoiceUIClientTypeUnknown,
    /** Amazon Alexa */
    IoTVoiceUIClientTypeAVS,
    /** Google Voice Assistant */
    IoTVoiceUIClientTypeGVA,
    /** Microsoft Cortana */
    IoTVoiceUIClientTypeCortana,
    /** Built-in Modular Client */
    IoTVoiceUIClientTypeModular
};

/**
 @brief Representation of an available Voice UI client.
 */
@interface IoTVoiceUIClient: NSObject
/**
 @brief The type of the client. For example Amazon Alexa.
 */
@property (nonatomic, readonly) IoTVoiceUIClientType type;
/**
 @brief Is the client currently onboarded.
 */
@property (nonatomic, readonly) BOOL onboarded;
/**
 @brief Is the speaker currently listening for the client's wake word
 */
@property (nonatomic, readonly) BOOL wakeWordEnabled;

/**
 @brief There is no public initializer for this class.
 */
- (instancetype)init NS_UNAVAILABLE;

@end

#pragma mark -

/**
 @brief Representation of a Bluetooth device.
 */
@interface IoTBluetoothDevice: NSObject
@property (nonatomic, readonly) NSString *name;
@property (nonatomic, readonly) NSString *address;
@end

#pragma mark -

typedef NS_ENUM(NSInteger, IoTZigbeeDeviceType) {
	/**
	 @brief Unknown device type.
     @discussion If it isn't a bulb or a thermostat then it will be unknown.
    */
    IoTZigbeeDeviceTypeUnknown,
    /** A light bulb */
    IoTZigbeeDeviceTypeLight,
    /** A thermostat */
    IoTZigbeeDeviceTypeThermostat
};

/**
 @brief Representation of a Zigbee device.
 */
@interface IoTZigbeeDevice: NSObject

/**
 @brief The human readable name of the Zigbee device
 */
@property (nonatomic, readonly) NSString *name;

/**
 @brief Identifier for this device.
 */
@property (nonatomic, readonly) NSUInteger identifier;

/**
 @brief The type of the device.
 */
@property (nonatomic, readonly) IoTZigbeeDeviceType type;
@end

#pragma mark -

/**
 @brief Representation of functionality exposed by IoTSys service running on speaker.
 @discussion There is no publicly available initializer for IoTDevice.
*/
@interface IoTDevice : NSObject

/**
 @brief There is no publicly available initializer for IoTDevice
*/
- (instancetype)init NS_UNAVAILABLE;

/**
 @brief The human readable name for the device.
*/
@property (nonatomic, readonly) NSString *displayName;

/**
 @brief Unique device ID for the IoTSys service running on the speaker
 */
@property (nonatomic, readonly) NSString *deviceID;

/**
 @brief The device manufacturer
 */
@property (nonatomic, readonly) NSString *manufacturer;

/**
 @brief The device model number
 */
@property (nonatomic, readonly) NSString *modelNumber;

/**
 @brief Asynchronously dispatch request to set the human readable name of the speaker.
 @discussion The completion block notes the request as successful if the POST succeeds. It does not ensure that the request was effected. Changes to the name via this method are also reflected in the displayName property of IoTPlayer.
 @param displayName the requested new name for the speaker.
 @param completion block to be called asynchronously upon completion (successful or otherwise).
 @param queue the dispatch queue to use when calling the completion block.
 */
- (void)setDisplayName:(NSString *)displayName
            completion:(nullable IoTCompletionHandler)completion
       completionQueue:(nullable dispatch_queue_t)queue;

/**
 @brief Asynchronously dispatch request to reboot the speaker.
 @param completion block to be called asynchronously upon completion (successful or otherwise).
 @param queue the dispatch queue to use when calling the completion block.
 */
- (void)rebootWithCompletion:(nullable IoTCompletionHandler)completion
             completionQueue:(nullable dispatch_queue_t)queue;

/**
 @brief Asynchronously dispatch request to perform a factory reset on the speaker.
 @param completion block to be called asynchronously upon completion (successful or otherwise).
 @param queue the dispatch queue to use when calling the completion block.
 */
- (void)factoryResetWithCompletion:(nullable IoTCompletionHandler)completion
                   completionQueue:(nullable dispatch_queue_t)queue;

#pragma mark Power

/**
 @brief Does the device support running on battery.
 */
@property (nonatomic, readonly) BOOL isBatteryPowerSupported;

/**
 @brief Is the device currently running on battery.
 */
@property (nonatomic, readonly) BOOL onBatteryPower;

/**
 @brief The charge level of the battery if preset.
 */
@property (nonatomic, readonly) uint chargeLevel;

/**
 @brief Time until the battery is exhausted.
 */
@property (nonatomic, readonly) int timeUntilBatteryDischarged;

/**
 @brief Time until the battery is fully charged.
 */
@property (nonatomic, readonly) int timeUntilBatteryCharged;

#pragma mark Networking

/**
 @brief Is the networking API supported
 */
@property (nonatomic, readonly) BOOL networkSupported;

/**
 @brief The network interface type currently in use by the device - wifi or ethernet.
 */
@property (nonatomic, readonly) IoTNetworkInterface networkInterface;

/**
 @brief If wifi is in use, the current IP address of the wifi adapter.
 */
@property (nonatomic, readonly) NSString *wifiIPAddress;

/**
 @brief If wifi is in use, the current MAC address of the wifi adapter.
 */
@property (nonatomic, readonly) NSString *wifiMacAddress;

/**
 @brief If ethernet is in use, the current IP address of the ethernet adapter.
 */
@property (nonatomic, readonly) NSString *ethernetIPAddress;

/**
 @brief If ethernet is in use, the current MAC address of the ethernet adapter.
 */
@property (nonatomic, readonly) NSString *ethernetMacAddress;

/**
 @brief If wifi is in use, the SSID of the wifi network to which the device is connected.
 */
@property (nonatomic, readonly) NSString *wifiSSID;

/**
 @brief If wifi is in use, the signal strength.
 @param numberOfBands provides the number of options available for graphical display (if there are four icons possible then provide 4 as the number of bands).
 */
- (uint)wifiQuality:(uint)numberOfBands;

/**
 @brief Asynchronously dispatch request to perform an update of the network info for the speaker.
 @discussion In general changes to the network state are notified to the mobile app through IoTivity notifications. However, the wifiQuality is not updated via this mechanism. To provide a near real-time state for this value, it is necessary to use this method to, in effect, poll the device.
 @param completion block to be called asynchronously upon completion (successful or otherwise).
 @param queue the dispatch queue to use when calling the completion block.
 */
- (void)updateNetworkInfoWithCompletion:(nullable IoTCompletionHandler)completion
                        completionQueue:(nullable dispatch_queue_t)queue;

#pragma mark Voice UI - General

/**
 @brief Does the device support voice UI.
 */
@property (nonatomic, readonly) BOOL voiceUISupported;

/**
 @brief Is Voice UI enabled on the device.
 */
@property (nonatomic, readonly) BOOL voiceUIEnabled;

/**
 @brief An array of the available voice UI clients (including unconfigured and disabled).
 */
@property (nonatomic, readonly) NSArray <IoTVoiceUIClient *> *voiceUIClients;

/**
 @brief The Voice UI client to be used when a wake word is not used - for example when a voice UI conversation is started with a button tap on the device.
 */
@property (nonatomic, readonly, nullable) IoTVoiceUIClient *defaultVoiceUIClient;

/**
 @brief Asynchronously dispatch request to enable/disable VoiceUI on the speaker.
 @discussion The completion block notes the request as successful if the POST succeeds. It does not ensure that the request was effected.
 @param enabled the new desired enabled state.
 @param completion block to be called asynchronously upon completion (successful or otherwise).
 @param queue the dispatch queue to use when calling the completion block.
 */
- (void)setVoiceUIEnabled:(BOOL)enabled
               completion:(nullable IoTCompletionHandler)completion
          completionQueue:(nullable dispatch_queue_t)queue;

/**
 @brief Asynchronously dispatch request to set the default VoiceUI on the speaker.
 @discussion The default Voice UI client is that to be used when a wake word is not used - for example when a voice UI conversation is started with a button tap on the device. The completion block notes the request as successful if the POST succeeds. It does not ensure that the request was effected.
 @param client the voiceUI client to be used as default.
 @param completion block to be called asynchronously upon completion (successful or otherwise).
 @param queue the dispatch queue to use when calling the completion block.
 */
- (void)setDefaultVoiceUIClient:(IoTVoiceUIClient *)client
                     completion:(nullable IoTCompletionHandler)completion
                completionQueue:(nullable dispatch_queue_t)queue;

/**
 @brief Asynchronously dispatch request to enable/disable wakeword detection for the given VoiceUI client.
 @discussion If wake word detection is disabled then the device no longer listens for the wake word for that service. The service still be used if it is the default Voice UI client and the conversation is initiated by other means.

     The completion block notes the request as successful if the POST succeeds. It does not ensure that the request was effected.
 @param client the voiceUI client to enable/disable wakeword detection for.
 @param wakeWordEnabled the new desired wakeword enabled state.
 @param completion block to be called asynchronously upon completion (successful or otherwise).
 @param queue the dispatch queue to use when calling the completion block.
 */
- (void)setVoiceUIClient:(IoTVoiceUIClient *)client
         wakeWordEnabled:(BOOL)wakeWordEnabled
              completion:(nullable IoTCompletionHandler)completion
         completionQueue:(nullable dispatch_queue_t)queue;

#pragma mark Voice UI - Modular

/**
 @brief Array of Languages available in the modular client
 */
@property (nonatomic, readonly) NSArray <NSString *> *modularClientLanguages;

/**
 @brief The currently used modular client language.
 */
@property (nonatomic, readonly, nullable) NSString *selectedModularClientLanguage;

/**
 @brief The currently used modular client alert file (currently unimplemented on device).
 */
@property (nonatomic, readonly) NSString * modularClientAlertFile;

/**
 @brief Asynchronously dispatch request to select the language used by the modular Voice UI client.
 @discussion The completion block notes the request as successful if the POST succeeds. It does not ensure that the request was effected.
 @param language the new desired language.
 @param completion block to be called asynchronously upon completion (successful or otherwise).
 @param queue the dispatch queue to use when calling the completion block.
 */
- (void)setSelectedModularClientLanguage:(NSString *)language
                              completion:(nullable IoTCompletionHandler)completion
                         completionQueue:(nullable dispatch_queue_t)queue;

/**
 @brief Asynchronously dispatch request to select the alert file used by modular Voice UI client (currently unimplemented on device).
 @discussion The completion block notes the request as successful if the POST succeeds. It does not ensure that the request was effected.
 @param file the new desired alert file.
 @param completion block to be called asynchronously upon completion (successful or otherwise).
 @param queue the dispatch queue to use when calling the completion block.
 */
- (void)setModularClientAlertFile:(NSString *)file
                       completion:(nullable IoTCompletionHandler)completion
                  completionQueue:(nullable dispatch_queue_t)queue;

#pragma mark Voice UI - AVS

/**
 @brief Array of available locales for the AVS Voice UI client
 */
@property (nonatomic, readonly) NSArray <NSString *> *avsLocales;

/**
 @brief The currently selected locale to be used by the AVS Voice UI Client.
 */
@property (nonatomic, readonly) NSString *selectedAVSLocale;

/**
 @brief Asynchronously dispatch request to select the desired locale to be used by AVS Voice UI client.
 @discussion The completion block notes the request as successful if the POST succeeds. It does not ensure that the request was effected.
 @param locale the new desired locale.
 @param completion block to be called asynchronously upon completion (successful or otherwise).
 @param queue the dispatch queue to use when calling the completion block.
 */
- (void)setSelectedAVSLocale:(NSString *)locale
          completion:(nullable IoTCompletionHandler)completion
     completionQueue:(nullable dispatch_queue_t)queue;

/**
 @brief Asynchronously dispatch request to start the onboarding process for the AVS Voice UI client.
 @discussion The AVS onboarding process requires the user to log in to their Amazon account using a URL provided by the device. The user should then enter an alphanumeric code also provided by the device. The device will then be authorised remotely without any further action by the user. The url and code are provided using a notification from IoTSys which is sent to the IoTClient delegate method using the -device:voiceUIDidProvideAVSAuthenticationCode:url: method.

 	 The completion block notes the request as successful if the POST succeeds. It does not ensure that the request was effected.
 @param completion block to be called asynchronously upon completion (successful or otherwise).
 @param queue the dispatch queue to use when calling the completion block.
 */
- (void)startAVSOnboardingWithCompletion:(nullable IoTCompletionHandler)completion
                         completionQueue:(nullable dispatch_queue_t)queue;

/**
 @brief Asynchronously dispatch request to delete the stored credentials for the AVS Voice UI client.
 @discussion The completion block notes the request as successful if the POST succeeds. It does not ensure that the request was effected. The DUT device should be rebooted once the change has been effected.
 @param completion block to be called asynchronously upon completion (successful or otherwise).
 @param queue the dispatch queue to use when calling the completion block.
 */
- (void)removeAVSCredentialWithCompletion:(nullable IoTCompletionHandler)completion
                          completionQueue:(nullable dispatch_queue_t)queue;

#pragma mark Bluetooth

/**
 @brief Does the device support Bluetooth.
 */
@property (nonatomic, readonly) BOOL bluetoothSupported;

/**
 @brief The enabled state of the bluetooth adapter of the device (enabled, disabled, unknown).
 */
@property (nonatomic, readonly) IoTBluetoothAdapterState bluetoothEnabled;

/**
 @brief The discoverable state of the bluetooth adapter of the device (discoverable, non-discoverable, unknown).
 */
@property (nonatomic, readonly) IoTDiscoverable bluetoothDiscoverable;

/**
 @brief The currently connected bluetooth device.
 */
@property (nonatomic, readonly, nullable) IoTBluetoothDevice *connectedBluetoothDevice;

/**
 @brief Array of bluetooth devices with which the speaker is currently paired.
 */
@property (nonatomic, readonly) NSArray<IoTBluetoothDevice *> *pairedBluetoothDevices;

/**
 @brief Is the bluetooth adapter currently scanning. This value is not definitive. It may return a false negative.
 */
@property (nonatomic, readonly) BOOL isBluetoothScanning;

/**
 @brief Asynchronously dispatch request to start an update of the current Bluetooth
 @discussion The completion block notes the request as successful if the POST succeeds. It does not ensure that the request was effected. The update will be performed asynchronously and notified through the IoTCleint delegate.
 @param completion block to be called asynchronously upon completion (successful or otherwise).
 @param queue the dispatch queue to use when calling the completion block.
 */
- (void)startUpdateBtAdapterStateWithCompletion:(nullable IoTCompletionHandler)completion
                          completionQueue:(nullable dispatch_queue_t)queue;

/**
 @brief Asynchronously dispatch request to enable/disable the bluetooth adapter.
 @discussion The completion block notes the request as successful if the POST succeeds. It does not ensure that the request was effected. Currently, enabling the Bluetooth adapter may also make the adapter discoverable or enter discovery mode without further action.
 @param enabled the new desired enabled state.
 @param completion block to be called asynchronously upon completion (successful or otherwise).
 @param queue the dispatch queue to use when calling the completion block.
 */
- (void)setBtAdapterEnabled:(BOOL)enabled
                 completion:(nullable IoTCompletionHandler)completion
            completionQueue:(nullable dispatch_queue_t)queue;

/**
 @brief Asynchronously dispatch request to make the bluetooth adapter on the speaker discoverable by other devices.
 @discussion The completion block notes the request as successful if the POST succeeds. It does not ensure that the request was effected.
 @param seconds the timeout for discoverable mode.
 @param completion block to be called asynchronously upon completion (successful or otherwise).
 @param queue the dispatch queue to use when calling the completion block.
 */
- (void)startBtDiscoveryModeWithTimeout:(UInt32)seconds
                             completion:(nullable IoTCompletionHandler)completion
                        completionQueue:(nullable dispatch_queue_t)queue;

/**
 @brief Asynchronously dispatch request to make the bluetooth adapter on the speaker leave discoverable mode.
 @discussion The completion block notes the request as successful if the POST succeeds. It does not ensure that the request was effected.
 @param completion block to be called asynchronously upon completion (successful or otherwise).
 @param queue the dispatch queue to use when calling the completion block.
 */
- (void)exitBtDiscoveryModeWithCompletion:(nullable IoTCompletionHandler)completion
                          completionQueue:(nullable dispatch_queue_t)queue;

/**
 @brief Asynchronously dispatch request to begin discovery of nearby bluetooth devices.
 @discussion The completion block notes the request as successful if the POST succeeds. It does not ensure that the request was effected.
 @param completion block to be called asynchronously upon completion (successful or otherwise).
 @param queue the dispatch queue to use when calling the completion block.
 */
- (void)startBtScanWithCompletion:(nullable IoTCompletionHandler)completion
                        completionQueue:(nullable dispatch_queue_t)queue;

/**
 @brief Asynchronously dispatch request to end discovery of nearby devices.
 @discussion The completion block notes the request as successful if the POST succeeds. It does not ensure that the request was effected.
 @param completion block to be called asynchronously upon completion (successful or otherwise).
 @param queue the dispatch queue to use when calling the completion block.
 */
- (void)stopBtScanWithCompletion:(nullable IoTCompletionHandler)completion
                 completionQueue:(nullable dispatch_queue_t)queue;

/**
 @brief Asynchronously dispatch request to connect with a previously discovered bluetooth device.
 @discussion The completion block notes the request as successful if the POST succeeds. It does not ensure that the request was effected.
 @param device the device to connect to.
 @param completion block to be called asynchronously upon completion (successful or otherwise).
 @param queue the dispatch queue to use when calling the completion block.
 */
- (void)startConnectBtDevice:(IoTBluetoothDevice *)device
                  completion:(nullable IoTCompletionHandler)completion
             completionQueue:(nullable dispatch_queue_t)queue;

/**
 @brief Asynchronously dispatch request to discconnect form a bluetooth device.
 @discussion The completion block notes the request as successful if the POST succeeds. It does not ensure that the request was effected.
 @param device the device to disconnect.
 @param completion block to be called asynchronously upon completion (successful or otherwise).
 @param queue the dispatch queue to use when calling the completion block.
 */
- (void)startDisconnectBtDevice:(IoTBluetoothDevice *)device
                     completion:(nullable IoTCompletionHandler)completion
                completionQueue:(nullable dispatch_queue_t)queue;

/**
 @brief Asynchronously dispatch request to clear the list of paired bluetooth devices.
 @discussion The completion block notes the request as successful if the POST succeeds. It does not ensure that the request was effected.
 @param completion block to be called asynchronously upon completion (successful or otherwise).
 @param queue the dispatch queue to use when calling the completion block.
 */
- (void)startClearPairedBtDevicesWithCompletion:(nullable IoTCompletionHandler)completion
                                completionQueue:(nullable dispatch_queue_t)queue;

/**
 @brief Asynchronously dispatch request to update the list of paired bluetooth devices.
 @discussion The completion block notes the request as successful if the POST succeeds. It does not ensure that the request was effected.
 @param completion block to be called asynchronously upon completion (successful or otherwise).
 @param queue the dispatch queue to use when calling the completion block.
 */
- (void)startUpdatePairedBtDevicesWithCompletion:(nullable IoTCompletionHandler)completion
                                completionQueue:(nullable dispatch_queue_t)queue;

/**
 @brief Asynchronously dispatch request to pair with a previously discovered bluetooth device.
 @discussion The completion block notes the request as successful if the POST succeeds. It does not ensure that the request was effected.
 @param device the device to pair with.
 @param completion block to be called asynchronously upon completion (successful or otherwise).
 @param queue the dispatch queue to use when calling the completion block.
 */
- (void)startPairBtDevice:(IoTBluetoothDevice *)device
               completion:(nullable IoTCompletionHandler)completion
          completionQueue:(nullable dispatch_queue_t)queue;

/**
 @brief Asynchronously dispatch request to unpair with a previously paired bluetooth device.
 @discussion The completion block notes the request as successful if the POST succeeds. It does not ensure that the request was effected.
 @param device the device to unpair.
 @param completion block to be called asynchronously upon completion (successful or otherwise).
 @param queue the dispatch queue to use when calling the completion block.
 */
- (void)startUnpairBtDevice:(IoTBluetoothDevice *)device
               completion:(nullable IoTCompletionHandler)completion
          completionQueue:(nullable dispatch_queue_t)queue;

#pragma mark Zigbee

/**
 @brief Does the device support Zigbee.
 */
@property (nonatomic, readonly) BOOL zigbeeSupported;

/**
 @brief The enabled state of the zigbee adapter of the device (enabled, disabled, unknown).
 */
@property (nonatomic, readonly) IoTZigbeeAdapterState zigbeeEnabled;

/**
 @brief The coordinator state of the zigbee adapter of the device (nominated, not-nominated, unknown).
 @discussion There must be, at most, one Zigbee coordinator on a given network.
 */
@property (nonatomic, readonly) IoTCoordinatorState zigbeeCoordinatorState;

/**
 @brief Array of the known (joined) Zigbee devices.
 */
@property (nonatomic, readonly) NSArray<IoTZigbeeDevice *> *zigbeeDevices;

/**
 @brief Asynchronously dispatch request to enable/disable the zigbee adapter.
 @discussion The completion block notes the request as successful if the POST succeeds. It does not ensure that the request was effected.
 @param enabled the new desired enabled state.
 @param completion block to be called asynchronously upon completion (successful or otherwise).
 @param queue the dispatch queue to use when calling the completion block.
 */
- (void)setZbAdapterEnabled:(BOOL)enabled
                 completion:(nullable IoTCompletionHandler)completion
            completionQueue:(nullable dispatch_queue_t)queue;

/**
 @brief Asynchronously dispatch request to become coordinator and form a network.
 @discussion This method is to used when there is no existing coordinator. The result of this call is that the target speaker will become the Zigbee coordinator. To allow Zigbee devices to join the new network, startZbJoiningWithTimeout: should be called.
 @param completion block to be called asynchronously upon completion (successful or otherwise).
 @param queue the dispatch queue to use when calling the completion block.
 */
- (void)startFormZbNetworkWithCompletion:(nullable IoTCompletionHandler)completion
                         completionQueue:(nullable dispatch_queue_t)queue;

/**
 @brief Asynchronously dispatch request to enter joining mode and allow devices to join the Zigbee network.
 @discussion This method is to used when a device has already been nominated as the Zigbee coordinator.
 @param seconds The time period to remain in joining mode.
 @param completion block to be called asynchronously upon completion (successful or otherwise).
 @param queue the dispatch queue to use when calling the completion block.
 */
- (void)startZbJoiningWithTimeout:(UInt32)seconds
                       completion:(nullable IoTCompletionHandler)completion
                  completionQueue:(nullable dispatch_queue_t)queue;

/**
 @brief Asynchronously dispatch request to set the human visible name of a zigbee device.
 @param name The new name for the Zigbee device.
 @param identifier The identifier for the Zigbee device.
 @param completion block to be called asynchronously upon completion (successful or otherwise).
 @param queue the dispatch queue to use when calling the completion block.
 */
- (void)startSetZbDeviceName:(NSString *)name
                   identifer:(NSUInteger)identifier
                  completion:(nullable IoTCompletionHandler)completion
             completionQueue:(nullable dispatch_queue_t)queue;

@end

NS_ASSUME_NONNULL_END
