//
//  GHDeviceSettings.h
//  Garmin Health
//
//  Created by Timar, Mihai on 12/08/15.
//  Copyright © 2016 Garmin International, Inc. or its affiliates. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "GHDeviceTypes.h"
#import "GHUserSettings.h"
#import "GHUserGoal.h"
#import "GHScreen.h"

@class GHDeviceSchema;
@class GHCIQApp;

/**
 *  The various orientations available on some activity trackers.
 */
typedef NS_ENUM(uint8_t, GHDisplayOrientation){ //maps to FIT_DISPLAY_ORIENTATION
    /** Standard Portrait orientation */
    GHDisplayOrientationPortrait = 1,
    
    /** Standard Landscape orientation */
    GHDisplayOrientationLandscape = 2,
    
    /** Upside down Portrait orientation */
    GHDisplayOrientationPortraitFlipped = 3,
    
    /** Upside down Landscape orientation */
    GHDisplayOrientationLandscapeFlipped = 4,
};

/**
 *  Available watch faces.
 */
typedef NS_ENUM(uint8_t, GHWatchFace){
    /** Traditional digital watchface */
    GHWatchFaceDigitalTraditional = 1,
    
    /** Modern digital watchface */
    GHWatchFaceDigitalModern = 2,
    
    /** Bold digital watchface */
    GHWatchFaceDigitalBold = 3,
    
    /** Minimal analog watchface */
    GHWatchFaceAnalogMinimal = 4,
    
    /** Traditional analog watchface */
    GHWatchFaceAnalogTraditional = 5,
    
    /** Digital time, move bar, battery watchface */
    GHWatchFaceDigitalGeneric1 = 6,
    
    /** Digital time watchface */
    GHWatchFaceDigitalGeneric2 = 7,
    
    /** Analog time watchface */
    GHWatchFaceAnalogGeneric3 = 8,
    
    /** Analog time watchface */
    GHWatchFaceAnalogGeneric4 = 9,
    
    /** Analog time, date watchface */
    GHWatchFaceAnalogGeneric5 = 10,
    
    /** Digital time, steps watchface */
    GHWatchFaceDigitalGeneric6 = 11,
    
    /** Digital time, heart rate watchface */
    GHWatchFaceDigitalGeneric7 = 12,
    
    /** Digital time, notifications watchface */
    GHWatchFaceDigitalGeneric8 = 13
};

/**
 *  How the backlight feature should operate if supported.
 */
typedef NS_ENUM(uint8_t, GHBacklightSetting){
    /** Always off */
    GHBacklightSettingOff = 0,
    
    /** Always on */
    GHBacklightSettingOn = 1,
    
    /** On only during activities */
    GHBacklightSettingDuringActivity = 2,
};

/**
 *  How information is displayed on the screen if supported.
 *  With a split screen two metrics are displayed at once.
 */
typedef NS_ENUM(uint8_t, GHScreenMode){
    /** A single metric is displayed on a screen */
    GHScreenModeSingle = 0,
    
    /** The screen is split vertically */
    GHScreenModeSplitVertical = 1,
    
    /** The screen is split horizontally */
    GHScreenModeSplitHorizontal = 2,
};

/**
 *  How the heart rate feature should operate if supported.
 */
typedef NS_ENUM(uint8_t, GHHeartRateMode){
    /** Always off */
    GHHeartRateOff = 1,
    
    /** Always on */
    GHHeartRateOn = 2,
    
    /** On only during activities */
    GHHeartRateDuringActivity = 3,
};

/**
 *  Time mode for the device's Time screen
 */
typedef NS_ENUM(uint8_t, GHTimeFormat){
    /**  Use 12H format */
    GHTimeFormat12Hours = 0,
    
    /** Use 24H format */
    GHTimeFormat24Hours = 1
};

/**
 *  Date format for the device's Date screen
 */
typedef NS_ENUM(uint8_t, GHDateFormat){
    /** Display "DD - MM" */
    GHDateFormatDayMonth = 0,
    
    /** Display "MM - DD" */
    GHDateFormatMonthDay = 1,
};

/**
 *  Measuring units to be used
 */
typedef NS_ENUM(uint8_t, GHUnitSystem){
    /** Metric system (distance in km) */
    GHUnitSystemMetric = 0,
    
    /** Statute (distance in mi) */
    GHUnitSystemStatute = 1,
};

/**
 *  Available Sync frequencies. Syncing more frequently
 *  will negatively impact battery life.
 */
typedef NS_ENUM(uint8_t, GHSyncFrequency){
    /** Never sync */
    GHSyncFrequencyNever = 0,
    
    /** Sync occationally */
    GHSyncFrequencyOccasionally = 1,
    
    /** Sync frequently */
    GHSyncFrequencyFrequent = 2,
    
    /** Sync once a day */
    GHSyncFrequencyOncePerDay = 3,
    
    /** Sync frequency is custom */
    GHSyncFrequencyCustom = 4,
};

/**
 *  Types to use to enable alerts on a device. Device will vibration and/or make a tone
 */
typedef NS_OPTIONS(NSInteger, GHAlertsTypes) {
    /** Move alerts */
    GHAlertsTypeMove = 1 << 0,
    /** SpO2 detection @note Set alert threshold using spo2AlertThreshold property  */
    GHAlertsTypeSpO2Detection = 1 << 1,
    /** Abnormal heart rate detection @note Set alert threshold using abnormalHeartRateAlertThreshold property  */
    GHAlertsTypeAbnormalHeartRate = 1 << 2,
    /** Push notifications received from iPhone  */
    GHAlertsTypePushNotifications = 1 << 3,
    /** Goal reached notificaiton  */
    GHAlertsTypeGoalsNotification = 1 << 4,
    /** Stress level  */
    GHAlertsTypeStressLevel = 1 << 5,
    /** Hourly chime  */
    GHAlertsTypeHourlyChime = 1 << 6,
    /** Hydration alert  */
    GHAlertsTypeHydration = 1 << 7,
    /** Activity detected alert  */
    GHAlertsTypeActivityDetected = 1 << 8
};


/**
 * Error codes with updating settings.
 */
typedef NS_ENUM(NSInteger, GHSettingsError) {
    /** Unexpected error */
    GHSettingsErrorUndefined = 0,
    
    /** Provided settings were nil */
    GHSettingsErrorSettingsEmpty = 1,
    
    /** The type of the setting didn't match device being updated */
    GHSettingsErrorDeviceTypeMismatch = 2,
    
    /** Required property was empty or out of range. */
    GHSettingsErrorInvalidProperty = 3,
    
    /** Communication with the device failed. */
    GHSettingsErrorDeviceCommunication = 4,
};


/** Error domain for the errors generated by this class */
extern NSString *const GHDeviceSettingsErrorDomain;

#pragma mark -
/**
 *  Container object for all settings supported by device. Must be initialized with a <GHDeviceTypes>
 *  to set appropriate defaults and to populate schema with details on supported settings.
 *  Refer to GHDeviceSchema for additional information.
 */
@interface GHDeviceSettings : NSObject <NSCoding, NSCopying>

/**
 *  Type of device. Settings can't be applied to a different device type.
 *  Refer to GHDeviceTypes for additional information.
*/
@property (nonatomic) GHDeviceTypes type;

/**
 *  Details on which settings are supported for the Garmin device.
 *  Refer to GHDeviceSchema for additional information.
 */
@property (nonatomic) GHDeviceSchema *schema;

/**
 *  Screens to be enabled on the Garmin device. Defaults to all supported by the device.
 *  Refer to GHScreen for additional information.
 *  @note Only used in the standard SDK
 */
@property (nonatomic) NSArray<GHScreen*> *screens;

/**
 *  Widgets to be enabled on the devices that support Connect IQ.
 *  Represents last set state. Defaults to nil.
 *  Refer to GHCIQApp for additional information.
 */
@property (nonatomic) NSArray<GHCIQApp*> *widgets;

/**
 *  Watch apps to be visible in the App start selection devices that support Connect IQ.
 *  Refer to GHCIQApp for additional information.
 */
@property (nonatomic) NSArray<GHCIQApp*> *watchApps;

/**
 *  Screen shown first, use 0 for last displayed.
 *  Refer to GHScreenType for additional information.
 *  @note Only used in the standard SDK
 */
@property (nonatomic) GHScreenType defaultScreen;

/**
 *  Portrait or Landscape orientation of display.
 *  Refer to GHDisplayOrientation for additional information.
 *  @note Only used in the standard SDK
 */
@property (nonatomic) GHDisplayOrientation displayOrientation;

/**
 *  When screen backlight is enabled.
 *  Refer to GHBacklightSetting for additional information.
 *  @note Only used in the standard SDK
 */
@property (nonatomic) GHBacklightSetting backlightSetting;

/**
 *  Screen mode of device.
 *  Refer to GHScreenMode for additional information.
 *  @note Only used in the standard SDK
 */
@property (nonatomic) GHScreenMode screenMode;

/**
 *  Heart rate mode of device.
 *  Refer to GHHeartRateMode for additional information.
 *  @note Only used in the standard SDK
 */
@property (nonatomic) GHHeartRateMode heartRateMode;

/**
 *  Watchface for device. Requires GHScreenModeSingle.
 *  Refer to GHWatchFace for additional information.
 *  @note Only used in the standard SDK
 */
@property (nonatomic) GHWatchFace watchFace;

/**
 *  User settings for the device
 *  Refer to GHUserSettings for additional information.
*/
@property (nonatomic) GHUserSettings *userSettings;

/**
 *  Time mode to be used on Time screen.
 *  Refer to GHTimeFormat for additional information.
 *  @note Only used in the standard SDK
 */
@property (nonatomic) GHTimeFormat timeFormat;

/**
 *  Date mode to be used on Date screen.
 *  Refer to GHDateFormat for additional information.
 *  @note Only used in the standard SDK
 */
@property (nonatomic) GHDateFormat dateFormat;

/**
 *  Prefered measuring system to be used.
 *  Refer to GHUnitSystem for additional information.
 *  @note Only used in the standard SDK
 */
@property (nonatomic) GHUnitSystem unitSystem;

/**
 *  Alerts to be displayed on the device.
 *  Refer to GHAlertsTypes for additional information.
 *  @note If you set moveAlertEnabled, moveIQEnabled, or spo2DetectionEnabled to YES
 *  then this property will be ignored.
 *  @note Only used in the standard SDK
 */
@property (nonatomic) GHAlertsTypes alerts;

/**
 *  Whether device should automatically attempt to upload. 
 *  See GHDeviceSchema for whether autoUpload and/or autoSyncFrequency are supported
 *  @note Only used in the standard SDK
 */
@property (nonatomic) BOOL autoUploadEnabled;

/**
 *  How frequently device should automatically attempt to upload.
 *  See GHDeviceSchema for whether autoUpload and/or autoSyncFrequency are supported 
 *  @note Only used in the standard SDK
 */
@property (nonatomic) GHSyncFrequency autoSyncFrequency;

/**
 *  The minimum number of steps that are required for autosync to occur.
 *  @note Requires autoSyncFrequency of GHSyncFrequencyCustom and that autoSyncCustomTime be reached
 */
@property (nonatomic) NSNumber *autoSyncCustomSteps;

/**
 *  The minimum number of minutes that are required for autosync to occur.
 *  @note Requires autoSyncFrequency of GHSyncFrequencyCustom and that autoSyncCustomSteps be reached
 */
@property (nonatomic) NSNumber *autoSyncCustomTime;

/**
 *  Whether device will provide a move alerts with vibration and/or tones
 *  @note If you set this property to YES the alerts property will be ignored.
 */
@property (nonatomic) BOOL moveAlertEnabled DEPRECATED_MSG_ATTRIBUTE("Use alerts type GHAlertsTypeMove instead.");

/**
 *  Whether the device should enable MoveIQ.
 *  @note If you set this property to YES the alerts property will be ignored.
 */
@property (nonatomic) BOOL moveIQEnabled DEPRECATED_MSG_ATTRIBUTE("Use alerts type GHAlertsTypeActivityDetected instead.");

/**
 *  Whether the device should enable SpO2 detection during sleep. The readings will be taken
 *  during the middle four hours of the sleep window.
 *  @note If you set this property to YES the alerts property will be ignored.
 */
@property (nonatomic) BOOL spo2DetectionEnabled DEPRECATED_MSG_ATTRIBUTE("Use alerts type GHAlertsTypeSpO2Detection instead.");

/**
 *  The SpO2 level where an alert is dislayed on the device.
 *  @note Must add GHSpO2Detection to alerts property to enable
 */
@property (nonatomic) NSNumber *spo2AlertThreshold;

/**
 *  The heart rate level where an alert is dislayed on the device.
 *  @note Must add GHAbnormalHeartRate to alerts property to enable
 */
@property (nonatomic) NSNumber *abnormalHeartRateAlertThreshold;

/**
 *  The text to display on the GHScreenCustomMessage.
 *  @note Can only contain ASCII characters.
 *  @note Only used in the standard SDK
 */
@property (nonatomic) NSString *customMessage;

/**
 *  Flag indicating if the updated properties of the GHDeviceSettings have been sent
 *  to the Garmin device.
 */
@property (nonatomic, readonly) BOOL isDirty;


#pragma mark - Methods
/**
 *  Initialize new settings for a device type
 *  @param type The GHDeviceTypes to initialize the settings for.
 */
- (instancetype) initWithDeviceType:(GHDeviceTypes)type NS_DESIGNATED_INITIALIZER;

/**
 *  Prefered initialization method. GHDeviceSettings objects can be created by either copying
 *  or encoding/decoding an existing object.
 *  @param coder The NSCoder to initialize the settings with.
 */
- (instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;
/**
 *  Initialize new settings with same values as an existing settings object.
 *  @param settings The GHDeviceSettings to initialize the settings with.
*/
- (instancetype) initWithDeviceSettings:(GHDeviceSettings *)settings;

/**
 *  Returns the list of goals for the user
 */
-(NSArray<GHUserGoal*>*)getSupportedUserGoals;

/**
 *  Returns the list of screens for the device
 */
-(NSArray<GHScreen*>*)getSupportedScreens;

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

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


@end
