// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
//
// Code generated by Microsoft (R) AutoRest Code Generator.
import Foundation
import azureSwiftRuntime
internal struct RegionData : RegionProtocol {
    public var code: String?
    public var name: String?
    public var regions: [RegionProtocol?]?

        enum CodingKeys: String, CodingKey {case code = "code"
        case name = "name"
        case regions = "regions"
        }

  public init()  {
  }

  public init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
      if container.contains(.code) {
        self.code = try container.decode(String?.self, forKey: .code)
    }
    if container.contains(.name) {
        self.name = try container.decode(String?.self, forKey: .name)
    }
    if container.contains(.regions) {
        self.regions = try container.decode([RegionData?]?.self, forKey: .regions)
    }
    if var pageDecoder = decoder as? PageDecoder  {
      if pageDecoder.isPagedData,
        let nextLinkName = pageDecoder.nextLinkName {
          pageDecoder.nextLink = try UnknownCodingKey.decodeStringForKey(decoder: decoder, keyForDecode: nextLinkName)
      }
    }
  }

  public func encode(to encoder: Encoder) throws {
    var container = encoder.container(keyedBy: CodingKeys.self)
    if self.code != nil {try container.encode(self.code, forKey: .code)}
    if self.name != nil {try container.encode(self.name, forKey: .name)}
    if self.regions != nil {try container.encode(self.regions as! [RegionData?]?, forKey: .regions)}
  }
}

extension DataFactory {
  public static func createRegionProtocol() -> RegionProtocol {
    return RegionData()
  }
}


// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
//
// Code generated by Microsoft (R) AutoRest Code Generator.
import Foundation
import azureSwiftRuntime
internal struct ResourceData : ResourceProtocol {
    public var id: String?
    public var name: String?
    public var type: String?

        enum CodingKeys: String, CodingKey {case id = "id"
        case name = "name"
        case type = "type"
        }

  public init()  {
  }

  public init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
      if container.contains(.id) {
        self.id = try container.decode(String?.self, forKey: .id)
    }
    if container.contains(.name) {
        self.name = try container.decode(String?.self, forKey: .name)
    }
    if container.contains(.type) {
        self.type = try container.decode(String?.self, forKey: .type)
    }
    if var pageDecoder = decoder as? PageDecoder  {
      if pageDecoder.isPagedData,
        let nextLinkName = pageDecoder.nextLinkName {
          pageDecoder.nextLink = try UnknownCodingKey.decodeStringForKey(decoder: decoder, keyForDecode: nextLinkName)
      }
    }
  }

  public func encode(to encoder: Encoder) throws {
    var container = encoder.container(keyedBy: CodingKeys.self)
    if self.id != nil {try container.encode(self.id, forKey: .id)}
    if self.name != nil {try container.encode(self.name, forKey: .name)}
    if self.type != nil {try container.encode(self.type, forKey: .type)}
  }
}

extension DataFactory {
  public static func createResourceProtocol() -> ResourceProtocol {
    return ResourceData()
  }
}


// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
//
// Code generated by Microsoft (R) AutoRest Code Generator.
import Foundation
import azureSwiftRuntime
internal struct TrackedResourceData : TrackedResourceProtocol, ResourceProtocol {
    public var id: String?
    public var name: String?
    public var type: String?
    public var tags: [String:String]?
    public var location: String?

        enum CodingKeys: String, CodingKey {case id = "id"
        case name = "name"
        case type = "type"
        case tags = "tags"
        case location = "location"
        }

  public init()  {
  }

  public init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
      if container.contains(.id) {
        self.id = try container.decode(String?.self, forKey: .id)
    }
    if container.contains(.name) {
        self.name = try container.decode(String?.self, forKey: .name)
    }
    if container.contains(.type) {
        self.type = try container.decode(String?.self, forKey: .type)
    }
    if container.contains(.tags) {
        self.tags = try container.decode([String:String]?.self, forKey: .tags)
    }
    if container.contains(.location) {
        self.location = try container.decode(String?.self, forKey: .location)
    }
    if var pageDecoder = decoder as? PageDecoder  {
      if pageDecoder.isPagedData,
        let nextLinkName = pageDecoder.nextLinkName {
          pageDecoder.nextLink = try UnknownCodingKey.decodeStringForKey(decoder: decoder, keyForDecode: nextLinkName)
      }
    }
  }

  public func encode(to encoder: Encoder) throws {
    var container = encoder.container(keyedBy: CodingKeys.self)
    if self.id != nil {try container.encode(self.id, forKey: .id)}
    if self.name != nil {try container.encode(self.name, forKey: .name)}
    if self.type != nil {try container.encode(self.type, forKey: .type)}
    if self.tags != nil {try container.encode(self.tags, forKey: .tags)}
    if self.location != nil {try container.encode(self.location, forKey: .location)}
  }
}

extension DataFactory {
  public static func createTrackedResourceProtocol() -> TrackedResourceProtocol {
    return TrackedResourceData()
  }
}


// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
//
// Code generated by Microsoft (R) AutoRest Code Generator.
import Foundation
import azureSwiftRuntime
internal struct TrafficFlowData : TrafficFlowProtocol {
    public var sourceIp: String?
    public var latitude: Double?
    public var longitude: Double?
    public var queryExperiences: [QueryExperienceProtocol?]?

        enum CodingKeys: String, CodingKey {case sourceIp = "sourceIp"
        case latitude = "latitude"
        case longitude = "longitude"
        case queryExperiences = "queryExperiences"
        }

  public init()  {
  }

  public init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
      if container.contains(.sourceIp) {
        self.sourceIp = try container.decode(String?.self, forKey: .sourceIp)
    }
    if container.contains(.latitude) {
        self.latitude = try container.decode(Double?.self, forKey: .latitude)
    }
    if container.contains(.longitude) {
        self.longitude = try container.decode(Double?.self, forKey: .longitude)
    }
    if container.contains(.queryExperiences) {
        self.queryExperiences = try container.decode([QueryExperienceData?]?.self, forKey: .queryExperiences)
    }
    if var pageDecoder = decoder as? PageDecoder  {
      if pageDecoder.isPagedData,
        let nextLinkName = pageDecoder.nextLinkName {
          pageDecoder.nextLink = try UnknownCodingKey.decodeStringForKey(decoder: decoder, keyForDecode: nextLinkName)
      }
    }
  }

  public func encode(to encoder: Encoder) throws {
    var container = encoder.container(keyedBy: CodingKeys.self)
    if self.sourceIp != nil {try container.encode(self.sourceIp, forKey: .sourceIp)}
    if self.latitude != nil {try container.encode(self.latitude, forKey: .latitude)}
    if self.longitude != nil {try container.encode(self.longitude, forKey: .longitude)}
    if self.queryExperiences != nil {try container.encode(self.queryExperiences as! [QueryExperienceData?]?, forKey: .queryExperiences)}
  }
}

extension DataFactory {
  public static func createTrafficFlowProtocol() -> TrafficFlowProtocol {
    return TrafficFlowData()
  }
}


// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
//
// Code generated by Microsoft (R) AutoRest Code Generator.
import Foundation
import azureSwiftRuntime
internal struct TrafficManagerGeographicHierarchyData : TrafficManagerGeographicHierarchyProtocol, ProxyResourceProtocol, ResourceProtocol {
    public var id: String?
    public var name: String?
    public var type: String?
    public var properties: GeographicHierarchyPropertiesProtocol?

        enum CodingKeys: String, CodingKey {case id = "id"
        case name = "name"
        case type = "type"
        case properties = "properties"
        }

  public init()  {
  }

  public init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
      if container.contains(.id) {
        self.id = try container.decode(String?.self, forKey: .id)
    }
    if container.contains(.name) {
        self.name = try container.decode(String?.self, forKey: .name)
    }
    if container.contains(.type) {
        self.type = try container.decode(String?.self, forKey: .type)
    }
    if container.contains(.properties) {
        self.properties = try container.decode(GeographicHierarchyPropertiesData?.self, forKey: .properties)
    }
    if var pageDecoder = decoder as? PageDecoder  {
      if pageDecoder.isPagedData,
        let nextLinkName = pageDecoder.nextLinkName {
          pageDecoder.nextLink = try UnknownCodingKey.decodeStringForKey(decoder: decoder, keyForDecode: nextLinkName)
      }
    }
  }

  public func encode(to encoder: Encoder) throws {
    var container = encoder.container(keyedBy: CodingKeys.self)
    if self.id != nil {try container.encode(self.id, forKey: .id)}
    if self.name != nil {try container.encode(self.name, forKey: .name)}
    if self.type != nil {try container.encode(self.type, forKey: .type)}
    if self.properties != nil {try container.encode(self.properties as! GeographicHierarchyPropertiesData?, forKey: .properties)}
  }
}

extension DataFactory {
  public static func createTrafficManagerGeographicHierarchyProtocol() -> TrafficManagerGeographicHierarchyProtocol {
    return TrafficManagerGeographicHierarchyData()
  }
}


// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
//
// Code generated by Microsoft (R) AutoRest Code Generator.
import Foundation
import azureSwiftRuntime
internal struct TrafficManagerNameAvailabilityData : TrafficManagerNameAvailabilityProtocol {
    public var name: String?
    public var type: String?
    public var nameAvailable: Bool?
    public var reason: String?
    public var message: String?

        enum CodingKeys: String, CodingKey {case name = "name"
        case type = "type"
        case nameAvailable = "nameAvailable"
        case reason = "reason"
        case message = "message"
        }

  public init()  {
  }

  public init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
      if container.contains(.name) {
        self.name = try container.decode(String?.self, forKey: .name)
    }
    if container.contains(.type) {
        self.type = try container.decode(String?.self, forKey: .type)
    }
    if container.contains(.nameAvailable) {
        self.nameAvailable = try container.decode(Bool?.self, forKey: .nameAvailable)
    }
    if container.contains(.reason) {
        self.reason = try container.decode(String?.self, forKey: .reason)
    }
    if container.contains(.message) {
        self.message = try container.decode(String?.self, forKey: .message)
    }
    if var pageDecoder = decoder as? PageDecoder  {
      if pageDecoder.isPagedData,
        let nextLinkName = pageDecoder.nextLinkName {
          pageDecoder.nextLink = try UnknownCodingKey.decodeStringForKey(decoder: decoder, keyForDecode: nextLinkName)
      }
    }
  }

  public func encode(to encoder: Encoder) throws {
    var container = encoder.container(keyedBy: CodingKeys.self)
    if self.name != nil {try container.encode(self.name, forKey: .name)}
    if self.type != nil {try container.encode(self.type, forKey: .type)}
    if self.nameAvailable != nil {try container.encode(self.nameAvailable, forKey: .nameAvailable)}
    if self.reason != nil {try container.encode(self.reason, forKey: .reason)}
    if self.message != nil {try container.encode(self.message, forKey: .message)}
  }
}

extension DataFactory {
  public static func createTrafficManagerNameAvailabilityProtocol() -> TrafficManagerNameAvailabilityProtocol {
    return TrafficManagerNameAvailabilityData()
  }
}


// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
//
// Code generated by Microsoft (R) AutoRest Code Generator.
import Foundation
import azureSwiftRuntime
internal struct TrafficManagerUserMetricsKeyModelData : TrafficManagerUserMetricsKeyModelProtocol, ProxyResourceProtocol, ResourceProtocol {
    public var id: String?
    public var name: String?
    public var type: String?
    public var key: String?

        enum CodingKeys: String, CodingKey {case id = "id"
        case name = "name"
        case type = "type"
        case key = "key"
        }

  public init()  {
  }

  public init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
      if container.contains(.id) {
        self.id = try container.decode(String?.self, forKey: .id)
    }
    if container.contains(.name) {
        self.name = try container.decode(String?.self, forKey: .name)
    }
    if container.contains(.type) {
        self.type = try container.decode(String?.self, forKey: .type)
    }
    if container.contains(.key) {
        self.key = try container.decode(String?.self, forKey: .key)
    }
    if var pageDecoder = decoder as? PageDecoder  {
      if pageDecoder.isPagedData,
        let nextLinkName = pageDecoder.nextLinkName {
          pageDecoder.nextLink = try UnknownCodingKey.decodeStringForKey(decoder: decoder, keyForDecode: nextLinkName)
      }
    }
  }

  public func encode(to encoder: Encoder) throws {
    var container = encoder.container(keyedBy: CodingKeys.self)
    if self.id != nil {try container.encode(self.id, forKey: .id)}
    if self.name != nil {try container.encode(self.name, forKey: .name)}
    if self.type != nil {try container.encode(self.type, forKey: .type)}
    if self.key != nil {try container.encode(self.key, forKey: .key)}
  }
}

extension DataFactory {
  public static func createTrafficManagerUserMetricsKeyModelProtocol() -> TrafficManagerUserMetricsKeyModelProtocol {
    return TrafficManagerUserMetricsKeyModelData()
  }
}


// TrafficRoutingMethod enumerates the values for traffic routing method.

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
//
// Code generated by Microsoft (R) AutoRest Code Generator.
public enum TrafficRoutingMethodEnum: String, Codable
{
// Geographic specifies the geographic state for traffic routing method.
    case Geographic = "Geographic"
// Performance specifies the performance state for traffic routing method.
    case Performance = "Performance"
// Priority specifies the priority state for traffic routing method.
    case Priority = "Priority"
// Weighted specifies the weighted state for traffic routing method.
    case Weighted = "Weighted"
}


// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
//
// Code generated by Microsoft (R) AutoRest Code Generator.
import Foundation
// CheckTrafficManagerRelativeDnsNameAvailabilityParametersProtocol is parameters supplied to check Traffic Manager
// name operation.
public protocol CheckTrafficManagerRelativeDnsNameAvailabilityParametersProtocol : Codable {
     var name: String? { get set }
     var type: String? { get set }
}


// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
//
// Code generated by Microsoft (R) AutoRest Code Generator.
import Foundation
// CloudErrorBodyProtocol is the content of an error returned by the Azure Resource Manager
public protocol CloudErrorBodyProtocol : Codable {
     var code: String? { get set }
     var message: String? { get set }
     var target: String? { get set }
     var details: [CloudErrorBodyProtocol?]? { get set }
}


// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
//
// Code generated by Microsoft (R) AutoRest Code Generator.
import Foundation
// CloudErrorProtocol is an error returned by the Azure Resource Manager
public protocol CloudErrorProtocol : Codable {
     var error: CloudErrorBodyProtocol? { get set }
}


// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
//
// Code generated by Microsoft (R) AutoRest Code Generator.
import Foundation
// DeleteOperationResultProtocol is the result of the request or operation.
public protocol DeleteOperationResultProtocol : Codable {
     var operationResult: Bool? { get set }
}


// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
//
// Code generated by Microsoft (R) AutoRest Code Generator.
import Foundation
// DnsConfigProtocol is class containing DNS settings in a Traffic Manager profile.
public protocol DnsConfigProtocol : Codable {
     var relativeName: String? { get set }
     var fqdn: String? { get set }
     var ttl: Int64? { get set }
}


// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
//
// Code generated by Microsoft (R) AutoRest Code Generator.
import Foundation
// EndpointPropertiesProtocol is class representing a Traffic Manager endpoint properties.
public protocol EndpointPropertiesProtocol : Codable {
     var targetResourceId: String? { get set }
     var target: String? { get set }
     var endpointStatus: EndpointStatusEnum? { get set }
     var weight: Int64? { get set }
     var priority: Int64? { get set }
     var endpointLocation: String? { get set }
     var endpointMonitorStatus: EndpointMonitorStatusEnum? { get set }
     var minChildEndpoints: Int64? { get set }
     var geoMapping: [String]? { get set }
}


// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
//
// Code generated by Microsoft (R) AutoRest Code Generator.
import Foundation
// EndpointProtocol is class representing a Traffic Manager endpoint.
public protocol EndpointProtocol : ProxyResourceProtocol {
     var properties: EndpointPropertiesProtocol? { get set }
}


// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
//
// Code generated by Microsoft (R) AutoRest Code Generator.
import Foundation
// GeographicHierarchyPropertiesProtocol is class representing the properties of the Geographic hierarchy used with the
// Geographic traffic routing method.
public protocol GeographicHierarchyPropertiesProtocol : Codable {
     var geographicHierarchy: RegionProtocol? { get set }
}


// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
//
// Code generated by Microsoft (R) AutoRest Code Generator.
import Foundation
// HeatMapEndpointProtocol is class which is a sparse representation of a Traffic Manager endpoint.
public protocol HeatMapEndpointProtocol : Codable {
     var resourceId: String? { get set }
     var endpointId: Int32? { get set }
}


// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
//
// Code generated by Microsoft (R) AutoRest Code Generator.
import Foundation
// HeatMapModelProtocol is class representing a Traffic Manager HeatMap.
public protocol HeatMapModelProtocol : ProxyResourceProtocol {
     var properties: HeatMapPropertiesProtocol? { get set }
}


// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
//
// Code generated by Microsoft (R) AutoRest Code Generator.
import Foundation
// HeatMapPropertiesProtocol is class representing a Traffic Manager HeatMap properties.
public protocol HeatMapPropertiesProtocol : Codable {
     var startTime: Date? { get set }
     var endTime: Date? { get set }
     var endpoints: [HeatMapEndpointProtocol?]? { get set }
     var trafficFlows: [TrafficFlowProtocol?]? { get set }
}


// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
//
// Code generated by Microsoft (R) AutoRest Code Generator.
import Foundation
// MonitorConfigProtocol is class containing endpoint monitoring settings in a Traffic Manager profile.
public protocol MonitorConfigProtocol : Codable {
     var profileMonitorStatus: ProfileMonitorStatusEnum? { get set }
     var _protocol: MonitorProtocolEnum? { get set }
     var port: Int64? { get set }
     var path: String? { get set }
     var intervalInSeconds: Int64? { get set }
     var timeoutInSeconds: Int64? { get set }
     var toleratedNumberOfFailures: Int64? { get set }
}


// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
//
// Code generated by Microsoft (R) AutoRest Code Generator.
import Foundation
// ProfileListResultProtocol is the list Traffic Manager profiles operation response.
public protocol ProfileListResultProtocol : Codable {
     var value: [ProfileProtocol?]? { get set }
}


// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
//
// Code generated by Microsoft (R) AutoRest Code Generator.
import Foundation
// ProfilePropertiesProtocol is class representing the Traffic Manager profile properties.
public protocol ProfilePropertiesProtocol : Codable {
     var profileStatus: ProfileStatusEnum? { get set }
     var trafficRoutingMethod: TrafficRoutingMethodEnum? { get set }
     var dnsConfig: DnsConfigProtocol? { get set }
     var monitorConfig: MonitorConfigProtocol? { get set }
     var endpoints: [EndpointProtocol?]? { get set }
}


// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
//
// Code generated by Microsoft (R) AutoRest Code Generator.
import Foundation
// ProfileProtocol is class representing a Traffic Manager profile.
public protocol ProfileProtocol : TrackedResourceProtocol {
     var properties: ProfilePropertiesProtocol? { get set }
}


// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
//
// Code generated by Microsoft (R) AutoRest Code Generator.
import Foundation
// ProxyResourceProtocol is the resource model definition for a ARM proxy resource. It will have everything other than
// required location and tags
public protocol ProxyResourceProtocol : ResourceProtocol {
}


// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
//
// Code generated by Microsoft (R) AutoRest Code Generator.
import Foundation
// QueryExperienceProtocol is class representing a Traffic Manager HeatMap query experience properties.
public protocol QueryExperienceProtocol : Codable {
     var endpointId: Int32 { get set }
     var queryCount: Int32 { get set }
     var latency: Double? { get set }
}


// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
//
// Code generated by Microsoft (R) AutoRest Code Generator.
import Foundation
// RegionProtocol is class representing a region in the Geographic hierarchy used with the Geographic traffic routing
// method.
public protocol RegionProtocol : Codable {
     var code: String? { get set }
     var name: String? { get set }
     var regions: [RegionProtocol?]? { get set }
}


// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
//
// Code generated by Microsoft (R) AutoRest Code Generator.
import Foundation
// ResourceProtocol is the core properties of ARM resources
public protocol ResourceProtocol : Codable {
     var id: String? { get set }
     var name: String? { get set }
     var type: String? { get set }
}


// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
//
// Code generated by Microsoft (R) AutoRest Code Generator.
import Foundation
// TrackedResourceProtocol is the resource model definition for a ARM tracked top level resource
public protocol TrackedResourceProtocol : ResourceProtocol {
     var tags: [String:String]? { get set }
     var location: String? { get set }
}


// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
//
// Code generated by Microsoft (R) AutoRest Code Generator.
import Foundation
// TrafficFlowProtocol is class representing a Traffic Manager HeatMap traffic flow properties.
public protocol TrafficFlowProtocol : Codable {
     var sourceIp: String? { get set }
     var latitude: Double? { get set }
     var longitude: Double? { get set }
     var queryExperiences: [QueryExperienceProtocol?]? { get set }
}


// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
//
// Code generated by Microsoft (R) AutoRest Code Generator.
import Foundation
// TrafficManagerGeographicHierarchyProtocol is class representing the Geographic hierarchy used with the Geographic
// traffic routing method.
public protocol TrafficManagerGeographicHierarchyProtocol : ProxyResourceProtocol {
     var properties: GeographicHierarchyPropertiesProtocol? { get set }
}


// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
//
// Code generated by Microsoft (R) AutoRest Code Generator.
import Foundation
// TrafficManagerNameAvailabilityProtocol is class representing a Traffic Manager Name Availability response.
public protocol TrafficManagerNameAvailabilityProtocol : Codable {
     var name: String? { get set }
     var type: String? { get set }
     var nameAvailable: Bool? { get set }
     var reason: String? { get set }
     var message: String? { get set }
}


// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
//
// Code generated by Microsoft (R) AutoRest Code Generator.
import Foundation
// TrafficManagerUserMetricsKeyModelProtocol is class representing a Traffic Manager Real User Metrics key response.
public protocol TrafficManagerUserMetricsKeyModelProtocol : ProxyResourceProtocol {
     var key: String? { get set }
}


// swift-tools-version:5.3
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
    name: "AzureMapsControl",
    platforms: [.iOS(.v14)],
    products: [
        .library(
            name: "AzureMapsControl",
            targets: ["AzureMapsControl", "MapControlDependencies"]
        )
    ],
    dependencies: [
        .package(
            name: "MapLibre GL Native",
            url: "https://github.com/maplibre/maplibre-gl-native-distribution.git",
            .exact("5.12.0")
        ),
        .package(
            name: "MSAL",
            url: "https://github.com/AzureAD/microsoft-authentication-library-for-objc",
            from: "1.1.0"
        )
    ],
    targets: [
        .binaryTarget(
            name: "AzureMapsControl",
            url: "https://github.com/Azure/azure-maps-ios-sdk-distribution/releases/download/1.0.0-pre.3/AzureMapsControl.xcframework.zip",
            checksum: "1e45c519faf6dce423752d1f86594718c202cf680af65a47289af6967600811a"
        ),
        .target(
            name: "MapControlDependencies",
            dependencies: [
                .product(
                    name: "Mapbox",
                    package: "MapLibre GL Native",
                    condition: .when(platforms: [.iOS])
                ),
                .product(
                    name: "MSAL",
                    package: "MSAL",
                    condition: .when(platforms: [.iOS])
                )
            ],
            path: "./Sources"
        )
    ]
)


//
// Copyright Â© 2021 Microsoft. All rights reserved.
//

// This file exists as a workaround to be able to add the MapLibre package as a dependency.
import Foundation


//
//  AppDelegate.swift
//  Engagement
//
//  Created by Microsoft on 08/02/2016.
//  Copyright Â© 2016 Microsoft. All rights reserved.
//

import UIKit
import MMDrawerController
import AdSupport //Just to print your device advertisingIdentifier
import SwiftyJSON
import MessageUI

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

  var window: UIWindow?
    private var popOver: UIPopoverPresentationController?

  //MARK: UIApplicationDelegate
  func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

    configureAzMESDK()

    Theme.prepareThemeAppearance()

    //Prepare drawer root naivigation
    let screenBounds = UIScreen.mainScreen().bounds

    let leftController = MenuViewController()
    let centerController = UINavigationController(rootViewController: HomeViewController())
    let drawer = MMDrawerController(centerViewController: centerController, leftDrawerViewController: leftController)
    drawer.shouldStretchDrawer = false
    drawer.maximumLeftDrawerWidth = min(screenBounds.width - 50, 310)//For iPad, not be too large
    drawer.openDrawerGestureModeMask = .PanningCenterView
    drawer.closeDrawerGestureModeMask = .All
    drawer.setDrawerVisualStateBlock(MMDrawerVisualState.parallaxVisualStateBlockWithParallaxFactor(2.0))
    drawer.setGestureCompletionBlock { (drawer, gesture) -> Void in
      UIApplication.checkStatusBarForDrawer(drawer)
    }
    self.window = UIWindow(frame: screenBounds)
    self.window?.backgroundColor = UIColor.blackColor()

    let drawerNav = UINavigationController(rootViewController: drawer)
    drawerNav.navigationBarHidden = true
    self.window?.rootViewController = drawerNav

    self.window?.makeKeyAndVisible()

    return true
  }

  func application(application: UIApplication,
    didReceiveRemoteNotification userInfo: [NSObject : AnyObject],
    fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void)
  {
    EngagementAgent.shared().applicationDidReceiveRemoteNotification(userInfo,
      fetchCompletionHandler: completionHandler)
  }

  func application(application: UIApplication, didReceiveLocalNotification notification: UILocalNotification) {
    //Only from background
    if application.applicationState != .Active{
      DeepLinkHelper.manageLocalNotification(notification.userInfo)
    }
  }

  func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
    EngagementAgent.shared().registerDeviceToken(deviceToken)
  }

  func application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError) {

    let notificationAlert = UIAlertController(title: "Notifications",
      message: L10n.tr("permission.message"),
      preferredStyle: UIAlertControllerStyle.Alert)

    notificationAlert.addAction(UIAlertAction(title: "Go to settings",
      style: .Default,
      handler:
      { (action: UIAlertAction!) in
        let settingsUrl = NSURL(string: UIApplicationOpenSettingsURLString)
        if let url = settingsUrl {
          UIApplication.sharedApplication().openURL(url)
        }
    }))
    notificationAlert.addAction(UIAlertAction(title: "Cancel",
      style: .Cancel,
      handler: { (action: UIAlertAction!) in
      notificationAlert.dismissViewControllerAnimated(true, completion: nil)
    }))
    self.window?.rootViewController?.presentViewController(notificationAlert, animated: true, completion: nil)
  }

  func application(app: UIApplication, openURL url: NSURL, options: [String : AnyObject]) -> Bool {
    return DeepLinkHelper.canManage(url)
  }

  func application(application: UIApplication, handleActionWithIdentifier identifier: String?, forLocalNotification notification: UILocalNotification, completionHandler: () -> Void) {

    if identifier == Config.Notifications.shareIdentifier {
      let textToShare = "Product feedback"
      let objectsToShare = [textToShare]
      let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)
      activityVC.popoverPresentationController?.sourceView = self.window?.rootViewController?.view
      self.window?.rootViewController?.presentViewController(activityVC, animated: true, completion: nil)
    }
    else if identifier == Config.Notifications.feedbackIdentifier {
      let mailComposerVC = MFMailComposeViewController()
      mailComposerVC.mailComposeDelegate = self
      mailComposerVC.setToRecipients([""])
      mailComposerVC.setSubject("Feedback about the recent update")
      mailComposerVC.setMessageBody("Say something", isHTML: false)
      mailComposerVC.navigationBar.tintColor = UIColor.whiteColor()

      // TODO: Need to updates this part.
      self.window?.rootViewController?.presentViewController(mailComposerVC, animated: true, completion: {
        UIApplication.setStatusBarStyle(.LightContent)
      })
    }
  }

  /**
   Configure default AzME SDK implemntation
   */
  func configureAzMESDK()
  {
    if let reachModule = AEReachModule.moduleWithNotificationIcon(UIImage(named: "")) as? AEReachModule {
      //Poll Notifications
      reachModule.registerPollController(PollViewController.classForCoder(), forCategory: kAEReachDefaultCategory)

      reachModule.registerNotifier(AzMENotifier(), forCategory: kAEReachDefaultCategory)
      reachModule.registerNotifier(AzMENotifier(), forCategory: Config.AzMESDK.popUpCategory)

      reachModule.registerAnnouncementController(AnnouncementViewController.classForCoder(),
        forCategory: kAEReachDefaultCategory)
      reachModule.registerAnnouncementController(FullscreenInterstitialViewController.classForCoder(),
        forCategory: Config.AzMESDK.interstitialCategory)
      reachModule.registerAnnouncementController(FullscreenInterstitialViewController.classForCoder(),
        forCategory: Config.AzMESDK.webAnnouncementCategory)

      reachModule.setAutoBadgeEnabled(true)
      reachModule.dataPushDelegate = self
      if Config.AzMESDK.endPoint.isEmpty == false{
        EngagementAgent.init(Config.AzMESDK.endPoint, modulesArray: [reachModule])
      }

    }
  }

}

//MARK: AEReachDataPushDelegate
extension AppDelegate: AEReachDataPushDelegate{

  func didReceiveStringDataPushWithCategory(category: String!, body: String!) -> Bool {
    if let dataFromString = body.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false) {
      let json = JSON(data: dataFromString)

      let isDiscountAvailable = json[Config.Product.DataPush.isDiscountAvailable].boolValue
      let discountRateInPercent = json[Config.Product.DataPush.discountRateInPercent].intValue

      let defaults = NSUserDefaults.standardUserDefaults()
      defaults.setBool(isDiscountAvailable, forKey: Config.Product.DataPush.isDiscountAvailable)
      defaults.setInteger(discountRateInPercent, forKey: Config.Product.DataPush.discountRateInPercent)
      defaults.synchronize()
      NSNotificationCenter.defaultCenter().postNotificationName(Config.Notifications.dataPushValuesUpdated, object: nil)
    }
    return true
  }
}

//MARK: MFMailComposeViewControllerDelegate
extension AppDelegate: MFMailComposeViewControllerDelegate{
  func mailComposeController(controller: MFMailComposeViewController, didFinishWithResult result: MFMailComposeResult, error: NSError?) {
    controller.dismissViewControllerAnimated(true, completion: nil)
  }
}


//
//  CenterViewController.swift
//  Engagement
//
//  Created by Microsoft on 10/02/2016.
//  Copyright Â© 2016 Microsoft. All rights reserved.
//

import UIKit

class CenterViewController: EngagementViewController {

  override func viewDidLoad() {
    super.viewDidLoad()
  }

  override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)

    if self.navigationController?.viewControllers.count <= 1
    {
      self.navigationItem.leftBarButtonItem = UIBarButtonItem(image: AzIcon.iconMenu(18).imageWithSize(CGSizeMake(18, 18)),
        style: .Plain,
        target: self,
        action: #selector(CenterViewController.toggleDrawer))
    }
  }

  func toggleDrawer(){
    self.mm_drawerController.toggleDrawerSide(.Left, animated: true) { [weak self] (finished) -> Void in
      if self?.mm_drawerController.openSide == .Left{
        UIApplication.setStatusBarStyle(.Default)
      }else{
        UIApplication.setStatusBarStyle(.LightContent)
      }
    }
  }
}


//
//  AboutViewController.swift
//  Engagement
//
//  Created by Microsoft on 19/02/2016.
//  Copyright Â© 2016 Microsoft. All rights reserved.
//

import UIKit

/*
Credits View Controller
*/
class AboutViewController: CenterViewController {

  @IBOutlet weak var ibWebView: UIWebView!

  override func viewDidLoad() {
    super.viewDidLoad()

    self.navigationItem.title = L10n.tr("menu.about.title")

    self.ibWebView.delegate = self
    if let aboutUrl = NSBundle.mainBundle().pathForResource("about", ofType: "html", inDirectory: "html")
    {
      self.ibWebView.loadRequest(NSURLRequest(URL: NSURL(fileURLWithPath: aboutUrl)))
    }
  }

  override func engagementActivityName() -> String! {
    return AnalyticsMonitor.Activities.About
  }

  private func openLink(link: String) {
    if let URL = NSURL(string: link) {
      let controller = AzMESafariController(URL: URL)
      self.navigationController?.presentViewController(controller, animated: true, completion: nil)
    }
  }
}

//MARK: UIWebViewDelegate
extension AboutViewController : UIWebViewDelegate {

  func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
    if let url = request.URL?.absoluteString {
      if (url.hasSuffix("smartnsoft")) {
        openLink(Config.URLs.smartnsoft)
      }
      else if (url.hasSuffix("github")) {
        openLink(Config.URLs.github)
      }
      else if (url.hasSuffix("application_license")) {
        openLink(Config.URLs.applicationsLicenses)
      }
      else if (url.hasSuffix("third_party_notices")) {
        openLink(Config.URLs.thirdParties)
      }
      else {
        return true
      }
      return false;
    }
    return true;

  }
}


//
//  HomeViewController.swift
//  Engagement
//
//  Created by Microsoft on 10/02/2016.
//  Copyright Â© 2016 Microsoft. All rights reserved.
//

import UIKit
import SafariServices

//MARK: HomeViewController
class HomeViewController: CenterViewController {

  private let kHeaderHeight = 50

  @IBOutlet weak var ibSubTitle: UILabel!
  @IBOutlet weak var ibMainTitle: UILabel!
  @IBOutlet weak var ibTopView: UIView!
  @IBOutlet weak var ibTableView: UITableView!
  @IBOutlet weak var ibLogo: UIImageView!

  var dataSource = HomeDataSource()

  //MARK: Overriding
  override func engagementActivityName() -> String! {
    return AnalyticsMonitor.Activities.Home
  }

  //MARK: View Life Cycle
  override func viewDidLoad()
  {
    super.viewDidLoad()

    self.ibMainTitle.text = L10n.tr("application.name")
    self.ibSubTitle.text = L10n.tr("home.subtitle")

    ibMainTitle.font = UIFont(named: UIFont.AppFont.Bold, size: 20)
    ibSubTitle.font = UIFont(named: UIFont.AppFont.Medium, size: 14)

    let image = AzIcon.iconLogoAzme(85).imageWithSize(CGSize(width: 60, height: 85))
    ibLogo.image = image .imageWithRenderingMode(.AlwaysTemplate)
    ibLogo.tintColor = .whiteColor()

    ibTopView.backgroundColor = UIColor(named: UIColor.Name.PrimaryTheme)
    ibTableView.alwaysBounceVertical = false
    ibTableView.separatorStyle = .None
    ibTableView.rowHeight = UITableViewAutomaticDimension
    ibTableView.estimatedRowHeight = 60
    ibTableView.registerNib(UINib(nibName: TextFeedCell.identifier, bundle: nil),
      forCellReuseIdentifier: TextFeedCell.identifier)
    ibTableView.registerNib(UINib(nibName: HighlightCell.identifier, bundle: nil),
      forCellReuseIdentifier: HighlightCell.identifier)

    self.reloadData()
    self.changeBackgroundAccordingToOffset()
  }

  //MARK: Private methods

  /**
  Reload current data like recent updates
  Note : _be sure to empty the dataSource if a refreshControl is going to be set_
  */
  private func reloadData(){
    UIApplication.showHUD()
    AzMEService.fetchAzMERecentUpdates(forHome: true) { (channels, error) -> Void in
      UIApplication.dismissHUD()

      let sectionUpdates = HomeSection(title: L10n.tr("home.recent.updates.title"),
        titleColor: UIColor(named: UIColor.Name.PrimaryTheme),
        bgColor: UIColor(named: UIColor.Name.SecondaryGrey),
        buttonTitle: L10n.tr("home.recent.updates.view.all"),
        action: {

      })

      self.dataSource.sections.insert((sectionUpdates, channels), atIndex: 0)
      self.ibTableView.beginUpdates()
      self.ibTableView.insertSections(NSIndexSet(index: 0),
        withRowAnimation: UITableViewRowAnimation.Fade)
      self.ibTableView.endUpdates()
    }
  }

  /**
   Change the tableview background color according to its offset.
   This enable the behavior to have the tableFooterView with an "infinite" height (same colors)
   */
  private func changeBackgroundAccordingToOffset(){
    if ibTableView.contentOffset.y < 0{
      self.ibTableView.backgroundColor = UIColor(named: UIColor.Name.SecondaryGrey)
    }else{
      self.ibTableView.backgroundColor = UIColor(named: UIColor.Name.SecondaryOrange)
    }
  }
}

//MARK: UIScrollViewDelegate
extension HomeViewController: UIScrollViewDelegate{
  func scrollViewDidScroll(scrollView: UIScrollView) {
    self.changeBackgroundAccordingToOffset()
  }
}

//MARK: UITableViewDataSource
extension HomeViewController: UITableViewDataSource {
  func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return dataSource.sections.count
  }

  func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return dataSource.sections[section].items.count
  }

  func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    if let channel = dataSource.sections[indexPath.section].items[indexPath.row] as? RecentUpdate{
      let cell = tableView.dequeueReusableCellWithIdentifier(TextFeedCell.identifier, forIndexPath: indexPath) as! TextFeedCell
      cell.updateWith(channel.title, subTitle: channel.pubDate, description: channel.description)

      return cell
    }
    else if let highligthTitle = dataSource.sections[indexPath.section].items[indexPath.row] as? String{
      let cell = tableView.dequeueReusableCellWithIdentifier(HighlightCell.identifier, forIndexPath: indexPath) as! HighlightCell

      cell.updateWith(highligthTitle)

      return cell
    }
    return UITableViewCell()

  }
}

//MARK: UITableViewDelegate
extension HomeViewController: UITableViewDelegate {

  func tableView(tableView: UITableView, shouldHighlightRowAtIndexPath indexPath: NSIndexPath) -> Bool {
    return indexPath.section != 1
  }

  func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

    tableView.deselectRowAtIndexPath(indexPath, animated: true)

    //open link
    if let channel = dataSource.sections[indexPath.section].items[indexPath.row] as? RecentUpdate,
      channelLink = channel.link
    {
      AnalyticsMonitor.Events.Home.clickArticleHome(channel.title, URL: channelLink)
      let webController = AzMESafariController(URL: NSURL(string: channelLink)!)
      webController.delegate = self

      self.navigationController?.presentViewController(webController, animated: true, completion: { () -> Void in
        UIApplication.setStatusBarStyle(.Default)
      })
    }

  }

  func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
    return 1
  }

  func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    let headerView = FeedHeader(frame: CGRect(x: 0, y: 0, width: Int(self.view.frame.size.width), height: kHeaderHeight))

    let section =  dataSource.sections[section].section

    headerView.updateWith(section.title,
      buttonTitle: section.buttonTitle,
      action: { [weak self] () -> Void in
        AnalyticsMonitor.sendActivityNamed(AnalyticsMonitor.Events.Home.viewAllUpdates, extras: nil)
        self?.navigationController?.pushViewController(RecentUpdatesController(), animated: true)
      },
      bgColor: section.bgColor,
      titleColor: section.titleColor)

    return headerView

  }

  func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return CGFloat(kHeaderHeight)
  }

}

//MARK: SFSafariViewControllerDelegate
extension HomeViewController: SFSafariViewControllerDelegate{
  func safariViewControllerDidFinish(controller: SFSafariViewController) {
    UIApplication.setStatusBarStyle(.LightContent)
  }
}


//
//  MenuViewController.swift
//  Engagement
//
//  Created by Microsoft on 08/02/2016.
//  Copyright Â© 2016 Microsoft. All rights reserved.
//

import UIKit

private let kTableLeftMargin: CGFloat = 20
private let kTableHeaderHeight: CGFloat = 25
private let kTableExpandableRow = 3

/// Left Side Menu
class MenuViewController: UIViewController {

  @IBOutlet weak var ibTableView: UITableView!

  var expendedItems = [MenuItem]()
  var expended = false
  var dataSource = [(sectionName: String, items: [MenuItem])]()
  var currentIndexPath = NSIndexPath(forRow: 0, inSection: 0)

  //MARK: View Life Cycle
  override func viewDidLoad() {
    super.viewDidLoad()

    //because drawer have to be able to push controller, it is embeded into a UINavContr. Fix with top View Xib and header adjustements
    let header = UIView(frame: CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 25))
    header.backgroundColor = .whiteColor()
    ibTableView.tableHeaderView = header

    ibTableView.registerNib(UINib(nibName: MenuCell.identifier, bundle: nil),
      forCellReuseIdentifier: MenuCell.identifier)

    self.dataSource = MenuItem.defaultDataSoruceFromMenuController(self)
    self.expendedItems = MenuItem.helpfulLinksFromMenuController(self)
    self.ibTableView.selectRowAtIndexPath(NSIndexPath(forRow: 0, inSection: 0),
      animated: false,
      scrollPosition: UITableViewScrollPosition.Top)
  }

  override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)

    ibTableView.selectRowAtIndexPath(self.currentIndexPath, animated: false, scrollPosition: .Middle)
  }

  //MARK: Events behaviors

  /**
  Open an Internet Link via a SafariViewController

  - parameter link: the string URL
  */
  func openLink(link: String){
    if let URL = NSURL(string: link) {
      let controller = AzMESafariController(URL: URL)
      self.navigationController?.presentViewController(controller, animated: true, completion: nil)
    }
  }

  /**
   Expand or collapse Helpful links inside the menu
   */
  func toogleLinks() {
    self.expended = !self.expended

    if self.expended == true{
      self.dataSource[1].items.insertContentsOf(expendedItems, at: kTableExpandableRow)
      self.ibTableView.beginUpdates()
      self.ibTableView.insertRowsAtIndexPaths([NSIndexPath(forRow: 3, inSection: 1),
        NSIndexPath(forRow: 4, inSection: 1),
        NSIndexPath(forRow: 5, inSection: 1),
        NSIndexPath(forRow: 6, inSection: 1),
        NSIndexPath(forRow: 7, inSection: 1)],
        withRowAnimation: .Fade)
      self.ibTableView.endUpdates()

    }else{
      self.dataSource[1].items.removeRange(Range(start: kTableExpandableRow,end: kTableExpandableRow + expendedItems.count))
      self.ibTableView.beginUpdates()
      self.ibTableView.deleteRowsAtIndexPaths([NSIndexPath(forRow: 3, inSection: 1),
        NSIndexPath(forRow: 4, inSection: 1),
        NSIndexPath(forRow: 5, inSection: 1),
        NSIndexPath(forRow: 6, inSection: 1),
        NSIndexPath(forRow: 7, inSection: 1)],
        withRowAnimation: .Fade)
      self.ibTableView.endUpdates()
    }
  }
}

// MARK: - UITableViewDelegate
extension MenuViewController : UITableViewDelegate {

  func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    let menuItem = dataSource[indexPath.section].items[indexPath.row]

    if indexPath.isEqual(self.currentIndexPath) == false || indexPath.row == kTableExpandableRow || menuItem.isChild == false {

      if let selectAction = menuItem.selectedCompletion{
        let cell = tableView.dequeueReusableCellWithIdentifier(MenuCell.identifier, forIndexPath: indexPath) as! MenuCell
        cell.toggleIndicator()
        selectAction()
      }
      else if let controller = menuItem.initViewController?()
      {
        self.currentIndexPath = indexPath
        self.mm_drawerController.setCenterViewController(UINavigationController(rootViewController: controller),
          withCloseAnimation: true,
          completion: { [weak self] (bool) in
            UIApplication.checkStatusBarForDrawer(self?.mm_drawerController)
          })
      }
    }else{
      self.closeDrawer()
    }
  }

  func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {

    let sectionTitle = dataSource[section].sectionName

    guard sectionTitle.isEmpty == false else{
      return nil
    }

    let headerView =  UIView(frame: CGRect(x: 0, y: 5, width: self.view.frame.size.width, height: kTableHeaderHeight))

    headerView.backgroundColor = UIColor(named: UIColor.Name.SecondaryText)

    let frame = CGRect(x: kTableLeftMargin,
      y: 0,
      width: headerView.frame.width - kTableLeftMargin,
      height: kTableHeaderHeight)

    let label = UILabel(frame: frame)
    label.font = UIFont(named: UIFont.AppFont.Medium, size: 15)
    label.text = sectionTitle
    label.textColor = .whiteColor()
    headerView.addSubview(label)

    return headerView

  }

  func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return dataSource[section].sectionName.isEmpty ? 0 : kTableHeaderHeight
  }

  func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return 50
  }
}

// MARK: - UITableViewDataSource
extension MenuViewController : UITableViewDataSource {

  func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return dataSource.count
  }

  func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return dataSource[section].items.count
  }

  func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let menuItem = dataSource[indexPath.section].items[indexPath.row]
    let cell = tableView.dequeueReusableCellWithIdentifier(MenuCell.identifier, forIndexPath: indexPath) as! MenuCell
    cell.menuItem = menuItem

    if menuItem.separator == true {
      cell.separatorInset = UIEdgeInsetsZero
    }else{
      cell.separatorInset = UIEdgeInsets(top: 0, left: cell.bounds.width, bottom: 0, right: 0)
    }
    return cell
  }

}


//
//  RecentUpdatesController.swift
//  Engagement
//
//  Created by Microsoft on 12/02/2016.
//  Copyright Â© 2016 Microsoft. All rights reserved.
//

import UIKit

/// Recent Updates Controller will display last Azure Mobile Engagement news
class RecentUpdatesController: CenterViewController {

  @IBOutlet weak var ibTableView: UITableView!

  var dataSource = [RecentUpdate]()

  //MARK: Overriding
  override func engagementActivityName() -> String! {
    return AnalyticsMonitor.Activities.RecentUpdates
  }

  //MARK: View Life Cycle
  override func viewDidLoad() {
    super.viewDidLoad()

    self.title = L10n.tr("menu.recent.product.updates.title")

    ibTableView.backgroundColor = UIColor(named: UIColor.Name.SecondaryGrey)
    self.ibTableView.separatorStyle = .None
    self.ibTableView.contentInset = UIEdgeInsetsMake(15, 0, 0, 0)
    self.ibTableView.estimatedRowHeight = 100
    self.ibTableView.rowHeight = UITableViewAutomaticDimension
    self.ibTableView.registerNib(UINib(nibName: TextFeedCell.identifier, bundle: nil),
      forCellReuseIdentifier: TextFeedCell.identifier)

    UIApplication.showHUD()
    AzMEService.fetchAzMERecentUpdates(forHome: false) { (recentUpdates, error) -> Void in
      UIApplication.dismissHUD()
      self.dataSource = recentUpdates
      self.ibTableView.reloadData()
    }
  }

  override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)

    if let selectedIndex = self.ibTableView.indexPathsForSelectedRows?.first{
      self.ibTableView.deselectRowAtIndexPath(selectedIndex, animated: true)
    }

    UIApplication.setStatusBarStyle(UIStatusBarStyle.LightContent)
  }
}

//MARK: UITableViewDelegate
extension RecentUpdatesController: UITableViewDelegate{
  func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    let updateItem = self.dataSource[indexPath.row]

    if let link = updateItem.link, linkURL = NSURL(string: link){
      AnalyticsMonitor.Events.RecentUpdates.clickArticle(updateItem.title, URL: link)
      let safariController = AzMESafariController(URL: linkURL)
      self.navigationController?.presentViewController(safariController,
        animated: true,
        completion: { () -> Void in
          UIApplication.setStatusBarStyle(UIStatusBarStyle.Default)
      })
    }
  }
}

//MARK: UITableViewDataSource
extension RecentUpdatesController: UITableViewDataSource{
  func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 1
  }

  func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return self.dataSource.count
  }

  func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier(TextFeedCell.identifier, forIndexPath: indexPath) as! TextFeedCell

    let updateItem = self.dataSource[indexPath.row]

    cell.updateWith(updateItem.title, subTitle: updateItem.pubDate, description: updateItem.description)

    return cell
  }

}


//
//  AnnouncementViewController.swift
//  Engagement
//
//  Created by Microsoft on 18/02/2016.
//  Copyright Â© 2016 Microsoft. All rights reserved.
//

import UIKit

protocol AnnouncementIntersticialDelegate{
  func didCloseIntersticial()
  func didOpenIntersticial()
}

/// AnnouncementViewController, for local and AzME SDK
class AnnouncementViewController: AEAnnouncementViewController {

  @IBOutlet weak var navBar: UINavigationBar!
  @IBOutlet weak var ibNavItemTitle: UINavigationItem!
  @IBOutlet weak var ibWebView: UIWebView!
  @IBOutlet weak var ibActionButton: UIButton!
  @IBOutlet weak var ibCloseButton: UIButton!
  @IBOutlet weak var ibSeparator: UIView!

  @IBOutlet weak var ibNavBarHeight: NSLayoutConstraint!
  private var isLocal: Bool = false

  private var announcementVM: AnnouncementViewModel?

  var intersticialDelegate: AnnouncementIntersticialDelegate?

  //MARK: Initialization
  override init!(announcement anAnnouncement: AEReachAnnouncement!) {
    super.init(announcement: anAnnouncement)
  }

  init(announcement anAnnouncement: AnnouncementViewModel, isLocal: Bool) {
    self.isLocal = true
    self.announcementVM = anAnnouncement
    super.init(nibName: nil, bundle: nil)
  }

  override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
    super.init(nibName: nil, bundle: nil)
  }

  required init?(coder aDecoder: NSCoder) {
    super.init(nibName: nil, bundle: nil)
  }

  //MARK: View Life Cycle
  override func viewDidLoad() {
    super.viewDidLoad()

    ibSeparator.backgroundColor = UIColor(named: UIColor.Name.LightGrey)
    ibActionButton.tintColor = UIColor(named: UIColor.Name.PrimaryTheme)
    ibCloseButton.tintColor = UIColor(named: UIColor.Name.PrimaryTheme)

    if let announcement = self.announcement{
      self.announcementVM = AnnouncementViewModel(fromAnnouncement: announcement)
    }

    //cast here, to improve
    if let _ = parentViewController as? FullscreenInterstitialViewController {
      // Do nothing
    }
    else if isLocal == true {
      self.ibNavBarHeight.constant = 0
    }

    if let actionTitle = announcementVM?.actionTitle where actionTitle.isEmpty == false {
      ibActionButton.setTitle(actionTitle, forState: .Normal)
    } else {
      ibActionButton.removeFromSuperview()
    }

    if let exitTitle = announcementVM?.exitTitle where exitTitle.isEmpty == false {
      ibCloseButton.setTitle(exitTitle, forState: .Normal)
    } else {
      ibCloseButton.removeFromSuperview()
    }

    self.title = announcementVM?.title
    self.ibNavItemTitle.title = announcementVM?.title
    let mainBundle = NSURL(fileURLWithPath: NSBundle.mainBundle().bundlePath)

    if let HTMLBody = announcementVM?.body{
      if announcementVM?.type == AEAnnouncementType.Text{
        let htmlContent = String(HTMLString: HTMLBody)
        ibWebView.loadHTMLString(htmlContent, baseURL: mainBundle)
      }else{
        ibWebView.loadHTMLString(HTMLBody, baseURL: mainBundle)
      }

    }
  }

  //MARK: Actions
  @IBAction func didTapActionButton(sender: AnyObject) {
    AnalyticsMonitor.sendActivityNamed(AnalyticsMonitor.Events.ReboundScreen.viewAll, extras: nil)
    if isLocal == true{
      self.announcementVM?.action?()
    } else {
      if let delegate = self.intersticialDelegate{
        delegate.didOpenIntersticial()
      }else{
        self.action()
      }

    }
  }

  @IBAction func didTapCloseButton(sender: AnyObject) {
    AnalyticsMonitor.sendActivityNamed(AnalyticsMonitor.Events.ReboundScreen.close, extras: nil)
    if isLocal == true{
      self.dismissViewControllerAnimated(true, completion: nil)
    }
    else{

      if let delegate = self.intersticialDelegate{
        delegate.didCloseIntersticial()
      }else{
        self.exit()
      }

    }
  }
}


//
//  FullscreenInterstitialViewController.swift
//  Engagement
//
//  Created by Microsoft on 26/02/2016.
//  Copyright Â© 2016 Microsoft. All rights reserved.
//

import Foundation

/// FullscreenInterstitialViewController, for local and AzME SDK
class FullscreenInterstitialViewController : AEAnnouncementViewController {

  @IBOutlet weak var ibAnnoncementView: UIView!
  @IBOutlet weak var ibcTopConstraint: NSLayoutConstraint!

  private var announcementVM: AnnouncementViewModel?

  //MARK: Initialization
  override init!(announcement anAnnouncement: AEReachAnnouncement!) {
    super.init(announcement: anAnnouncement)
  }

  init(announcement anAnnouncement: AnnouncementViewModel, isLocal: Bool) {
    self.announcementVM = anAnnouncement
    super.init(nibName: nil, bundle: nil)
  }

  override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
    super.init(nibName: nil, bundle: nil)
  }

  required init?(coder aDecoder: NSCoder) {
    super.init(nibName: nil, bundle: nil)
  }

  override func viewDidLoad() {
    super.viewDidLoad()

    let annoncementViewController: AnnouncementViewController
    if self.announcement != nil {
      annoncementViewController = AnnouncementViewController(announcement: self.announcement)
      annoncementViewController.intersticialDelegate = self
      self.ibcTopConstraint.constant = 10
    } else {
      annoncementViewController = AnnouncementViewController(announcement: announcementVM!, isLocal: true)
    }

    self.addChildViewController(annoncementViewController)
    annoncementViewController.view.frame = CGRectMake(0, 0, ibAnnoncementView.frame.size.width, ibAnnoncementView.frame.size.height);
    self.addChildViewController(annoncementViewController)
    self.ibAnnoncementView.addSubview(annoncementViewController.view)
    annoncementViewController.didMoveToParentViewController(self)
    annoncementViewController.view.layer.cornerRadius = 10
    annoncementViewController.view.layer.masksToBounds = true
    self.ibAnnoncementView.layer.cornerRadius = 10
    self.ibAnnoncementView.layer.masksToBounds = true
    self.ibAnnoncementView.layer.shadowOffset = CGSize(width: 0, height: 0)
    self.ibAnnoncementView.layer.shadowColor = UIColor.blackColor().CGColor
    self.ibAnnoncementView.layer.shadowOpacity = 1
    self.ibAnnoncementView.layer.shadowRadius = 5
    self.ibAnnoncementView.clipsToBounds = false
  }

}

extension FullscreenInterstitialViewController: AnnouncementIntersticialDelegate{
  func didOpenIntersticial() {
    self.action()
  }

  func didCloseIntersticial() {
    self.exit()
  }
}


//
//  GetDeviceIdViewController.swift
//  Engagement
//
//  Created by Microsoft on 11/02/2016.
//  Copyright Â© 2016 Microsoft. All rights reserved.
//

import UIKit

/// To Share the AzME device ID
class GetDeviceIdViewController: CenterViewController {

  @IBOutlet weak var ibIcon: UIImageView!
  @IBOutlet weak var ibShareButton: AzButton!

  override func engagementActivityName() -> String! {
    return AnalyticsMonitor.Activities.GetDeviceID
  }

  //MARK: View Life Cycle
  override func viewDidLoad() {
    super.viewDidLoad()

    self.title = L10n.tr("menu.get.device.id.title")

    ibShareButton.setImage(UIImage(named: "share")?.imageWithRenderingMode(.AlwaysTemplate), forState: .Normal)

    ibIcon.image = AzIcon.iconMenGetDeviceID(60).imageWithSize(CGSize(width: 60, height: 60)).imageWithRenderingMode(.AlwaysTemplate)
    ibIcon.tintColor = UIColor(named: UIColor.Name.LightGrey)
  }

  //MARK: Actions
  @IBAction func didTapShareButton(sender: AnyObject)
  {
    AnalyticsMonitor.sendActivityNamed(AnalyticsMonitor.Events.GetDeviceID.share, extras: nil)
    if let azmeDeviceIdentifier = EngagementAgent.shared()?.deviceId(){
      let objectsToShare = [azmeDeviceIdentifier]
      dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0))
      {
        let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)
        if UIDevice.currentDevice().userInterfaceIdiom == .Pad{
          activityVC.popoverPresentationController?.sourceView = self.ibShareButton
          activityVC.popoverPresentationController?.sourceRect = self.ibShareButton.bounds
        }
        activityVC.completionWithItemsHandler = { (activityTypeString, completed, items, error) in
          if completed == true && error == nil{
            if (activityTypeString == UIActivityTypeCopyToPasteboard){
              AnalyticsMonitor.sendActivityNamed(AnalyticsMonitor.Events.GetDeviceID.copy, extras: nil)
            }else{
              AnalyticsMonitor.sendActivityNamed(AnalyticsMonitor.Events.GetDeviceID.share, extras: nil)
            }
          }
        }
        dispatch_async(dispatch_get_main_queue()) {
          self.presentViewController(activityVC, animated: true, completion: nil)
        }
      }
    }
  }
}


//
//  NotificationsViewController.swift
//  Engagement
//
//  Created by Microsoft on 15/02/2016.
//  Copyright Â© 2016 Microsoft. All rights reserved.
//

import UIKit

/*
This View Controller class is used for all Notifications demonstration scenarios.
*/
class NotificationsViewController: CenterViewController {

  @IBOutlet weak var ibTableView: UITableView!
  @IBOutlet weak var ibHowToButton: UIButton!

  var notificationScreen: NotificationScreen?
  var screenType: ScreenType?

  //MARK: Initialization
  init(notifScreen: ScreenType){
    self.screenType = notifScreen
    super.init(nibName: nil, bundle: nil)
  }

  required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
  }

  //MARK: Overriding
  override func engagementActivityName() -> String! {
    if let screenType = self.screenType{
      return AnalyticsMonitor.Activities.ActivitiesExtras.notificationExtraValueForType(screenType)
    }
    return "NotificationsViewController"
  }

  //MARK: View Life Cycle
  override func viewDidLoad() {
    super.viewDidLoad()

    if hasPushEnabled() == false {
      let settings = UIUserNotificationSettings(forTypes: [UIUserNotificationType.Alert,
        UIUserNotificationType.Badge,
        UIUserNotificationType.Sound],
        categories: nil)
      UIApplication.sharedApplication().registerUserNotificationSettings(settings)
      UIApplication.sharedApplication().registerForRemoteNotifications()
      self.dismissViewControllerAnimated(true, completion: {});
    }

    self.view.backgroundColor = UIColor(named: UIColor.Name.PrimaryTheme)

    self.ibHowToButton.backgroundColor = UIColor(named: UIColor.Name.PrimaryThemeLight)
    self.ibHowToButton.titleLabel?.font = UIFont(named: UIFont.AppFont.Regular, size: 15)
    self.ibHowToButton.setTitle(L10n.tr("out.of.app.push.notifications.footer.text"), forState: .Normal)
    self.ibHowToButton.titleLabel?.numberOfLines = 0
    self.ibHowToButton.titleLabel?.textAlignment = .Center

    self.ibTableView.separatorStyle = .SingleLine
    self.ibTableView.separatorColor = UIColor.whiteColor().colorWithAlphaComponent(0.4)
    self.ibTableView.separatorInset = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 10)
    self.ibTableView.backgroundColor = UIColor(named: UIColor.Name.PrimaryThemeLight)
    self.ibTableView.allowsSelection = false
    self.ibTableView.rowHeight = UITableViewAutomaticDimension
    self.ibTableView.estimatedRowHeight = 100
    self.ibTableView.registerNib(UINib(nibName: NotifiActionCell.identifier, bundle: nil),
      forCellReuseIdentifier: NotifiActionCell.identifier)

    let footerView = SimpleHeaderLabel(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: 20))
    footerView.update(UIFont(named: UIFont.AppFont.Bold, size: 13),
      mainTitle: self.screenType?.footerLabelTitle,
      headerType: HeaderViewType.TableHeader)
    self.ibTableView.setAndLayoutTableFooterView(footerView)

    if let screenType = self.screenType{
      self.notificationScreen = NotificationScreen(rootController: self, screenType: screenType)
      self.title = self.screenType?.maintTitle
    }

    let headerView = NotifTableHeader()
    headerView.update(self.notificationScreen?.screenType.image,
      mainTitle: self.notificationScreen?.screenType.message)
    self.ibTableView.setAndLayoutTableHeaderView(headerView)
    self.ibTableView.reloadData()
  }

  override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    self.ibTableView.layoutTableHeaderView()
    self.ibTableView.layoutTableFooterView()
  }

  @IBAction func didHowToButtonTap(sender: AnyObject) {
    if let screenType = self.screenType {
      let webController = WebViewController(howToNotificationType: screenType)
      self.navigationController?.pushViewController(webController, animated: true)
    }
  }

  func hasPushEnabled() -> Bool {
    if UIApplication.sharedApplication().respondsToSelector(#selector(UIApplication.currentUserNotificationSettings)) == true {
      let settings = UIApplication.sharedApplication().currentUserNotificationSettings()
      if (settings?.types.contains(.Alert) == true){
        return true
      }
    }
    return false;
  }

}

//MARK: UITableViewDataSource
extension NotificationsViewController: UITableViewDataSource{
  func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 1
  }

  func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if let nbItems = self.notificationScreen?.dataSource?.count{
      return nbItems
    }
    return 0
  }

  func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCellWithIdentifier(NotifiActionCell.identifier, forIndexPath: indexPath) as! NotifiActionCell

    if let notificationItem = self.notificationScreen?.dataSource?[indexPath.row]{
      cell.update(notificationItem, index: indexPath, delegate: self)
    }
    if let count = self.notificationScreen?.dataSource?.count{
      if (indexPath.row == count - 1) {
        cell.separatorInset = UIEdgeInsetsMake(0, cell.bounds.size.width, 0, 0);
      }
    }
    cell.backgroundColor = .clearColor()
    return cell
  }
}

//MARK: NotifActionDelegate
extension NotificationsViewController: NotifActionDelegate {

  func didTapButton(atIndex: NSIndexPath?) {
    if let index = atIndex, notificationItem = self.notificationScreen?.dataSource?[index.row]{
      notificationItem.action()
    }
  }

}


//
//  PermissionViewController.swift
//  Engagement
//
//  Created by Microsoft on 02/03/2016.
//  Copyright Â© 2016 Microsoft. All rights reserved.
//

import Foundation

/// Tell the user to accept receive notifications
class PermissionViewController : UIViewController {

  @IBOutlet weak var ibLabel: UILabel!
  @IBOutlet weak var ibButton: AzButton!

  override func viewDidLoad() {
    super.viewDidLoad()

    ibLabel.text = L10n.tr("permission.message")

    ibButton.titleLabel?.font = UIFont(named: UIFont.AppFont.Medium, size: 20)
    ibButton.setBackgroundImage(UIColor.imageWithColor(UIColor(named: UIColor.Name.SecondaryOrange)) , forState: .Normal)
  }

  @IBAction func didOkButtonTap(sender: AnyObject) {

  }

}


//
//  PollViewController.swift
//  Engagement
//
//  Created by Microsoft on 22/02/2016.
//  Copyright Â© 2016 Microsoft. All rights reserved.
//

import UIKit

/// Poll ViewController for local and AzME SDK
class PollViewController: AEPollViewController {

  @IBOutlet weak var ibDismissButton: AzButton!
  @IBOutlet weak var ibActionButton: AzButton!
  @IBOutlet weak var ibTableView: UITableView!
  @IBOutlet weak var ibNavBar: UINavigationBar!
  @IBOutlet weak var ibcNavBarHeight: NSLayoutConstraint!
  @IBOutlet weak var ibNavBarTitleItem: UINavigationItem!

  private var isFake = false
  private var hasBody = false
  private var selectedChoices = [String : (choiceId: String, indexPath: NSIndexPath)]()

  var reachPollViewModel : PollViewModel?

  //MARK: Initialization
  override init!(poll: AEReachPoll!) {
    super.init(nibName: "PollViewController", bundle: nil)
    self.poll = poll
    self.reachPollViewModel = PollViewModel(fromPoll: poll)
  }

  init(pollModel: PollViewModel){
    super.init(nibName: "PollViewController", bundle: nil)
    self.reachPollViewModel = pollModel
    self.isFake = true
  }

  required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
  }

  //MARK: View Life Cycle
  override func viewDidLoad() {
    super.viewDidLoad()
    if self.isFake == true{
      self.ibcNavBarHeight.constant = 0
      self.title = self.reachPollViewModel?.title
    }
    self.ibNavBarTitleItem.title = self.reachPollViewModel?.title
    self.view.backgroundColor = UIColor(named: UIColor.Name.PrimaryThemeLight)

    self.ibTableView.backgroundColor = UIColor(named: UIColor.Name.PrimaryThemeLight)
    self.ibTableView.rowHeight = UITableViewAutomaticDimension
    self.ibTableView.estimatedRowHeight = 60
    self.ibTableView.allowsMultipleSelection = true
    let headerView = SimpleHeaderLabel(frame: CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 20))
    let attributedString = NSMutableAttributedString()
    if self.isFake == true {
      attributedString.appendAttributedString(NSAttributedString(string: "A sample poll/survey notification\n\n",
        attributes: [NSFontAttributeName : UIFont(named: UIFont.AppFont.Bold, size: 13)]))
    }
    if let body = self.reachPollViewModel?.body{
      attributedString.appendAttributedString(NSAttributedString(string: body,
        attributes: [NSFontAttributeName : UIFont(named: UIFont.AppFont.Regular, size: 22)]))
    }
    headerView.updateAttributed(attributedString, headerType: HeaderViewType.TableHeader)
    self.ibTableView.setAndLayoutTableHeaderView(headerView)

    self.ibTableView.registerNib(UINib(nibName: PollChoiceCell.identifier, bundle: nil),
      forCellReuseIdentifier: PollChoiceCell.identifier)
    self.ibTableView.tableFooterView = UIView()
    self.ibTableView.separatorStyle = .None

    self.hasBody = self.reachPollViewModel?.body.isEmpty ?? false

    if let exitTitle = self.reachPollViewModel?.exitTitle where exitTitle.isEmpty == false {
      ibDismissButton.setTitle(exitTitle.uppercaseString, forState: .Normal)
    } else {
      ibDismissButton.removeFromSuperview()
    }
    if let actionTitle = self.reachPollViewModel?.actionTitle where actionTitle.isEmpty == false {
      ibActionButton.setTitle(actionTitle.uppercaseString, forState: .Normal)
    } else {
      ibActionButton.removeFromSuperview()
    }

    self.ibActionButton.setBackgroundImage(UIColor.imageWithColor(UIColor(named: UIColor.Name.SecondaryPurple).colorWithAlphaComponent(0.6)),
      forState: UIControlState.Disabled)
    self.ibActionButton.setBackgroundImage(UIColor.imageWithColor(UIColor(named: UIColor.Name.SecondaryPurple)),
      forState: .Normal)
    self.ibDismissButton.setBackgroundImage(UIColor.imageWithColor(UIColor(named: UIColor.Name.PrimaryTheme)),
      forState: .Normal)

    updateActionButtonState()
    // Do any additional setup after loading the view.
  }

  override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    self.ibTableView.layoutTableHeaderView()
  }

  //MARK: Actions
  @IBAction func didTapExitButton(sender: AnyObject) {
    if isFake == true{
      self.dismissViewControllerAnimated(true, completion: nil)
    }
    else{
      self.exitButtonClicked(sender)
    }
  }

  @IBAction func didTapActionButton(sender: AnyObject) {
    if self.isFake == true{
      self.reachPollViewModel?.action?()

    }
    else{
      var answers = [String : String]()

      for (key, tupleChoice) in self.selectedChoices{
        answers[key] = tupleChoice.choiceId
      }
      self.submitAnswers(answers)
      DeepLinkHelper.presentViewController(SuccessPollViewController(), animated: false)
    }
  }

  /**
   Update the state of the action button.
   Button is disable when not all question have a choice
   */
  func updateActionButtonState(){
    self.ibActionButton.enabled = (self.selectedChoices.count == self.reachPollViewModel?.questions.count && self.selectedChoices.count > 0)
  }

  /**
   Retrieve the correct choice ViewModel at index

   - parameter fromIndex: the data source index path

   - returns: a PollChoiceViewModel
   */
  func choice(fromIndex: NSIndexPath) -> PollChoiceViewModel?{

    if let question = self.question(fromIndex){
      return question.choices[fromIndex.row]
    }
    return nil
  }

  /**
   Retrieve the correct question ViewModel at index

   - parameter fromIndex: the data source index path

   - returns: a PollQuestionViewModel
   */
  func question(fromIndex: NSIndexPath) -> PollQuestionViewModel?{
    return self.reachPollViewModel?.questions[fromIndex.section]
  }

}

//MARK: UITableViewDataSource
extension PollViewController: UITableViewDataSource{
  func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return self.reachPollViewModel?.questions.count ?? 0
  }

  func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if let question = self.reachPollViewModel?.questions[section]{
      return question.choices.count
    }
    return 0
  }

  func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier(PollChoiceCell.identifier, forIndexPath: indexPath) as! PollChoiceCell

    //retrieve choice, update title
    if let choice = self.choice(indexPath){
      cell.update(choice.title)
    }

    return cell
  }
}

//MARK: UITableViewDelegate
extension PollViewController: UITableViewDelegate{

  func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {

    let headerView = SimpleHeaderLabel(frame: CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 30))

    if let question = self.question(NSIndexPath(forRow: 0, inSection: section)){
      headerView.update(UIFont(named: UIFont.AppFont.Bold, size: 18),
        mainTitle: question.title,
        headerType: HeaderViewType.SectionHeader)
    }

    return headerView
  }

  func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    if let question = self.question(NSIndexPath(forRow: 0, inSection: section)){
      return SimpleHeaderLabel.headerHeight(UIFont(named: UIFont.AppFont.Bold, size: 18),
        forTitle: question.title,
        insideWidth: self.view.frame.size.width,
        headerType: HeaderViewType.SectionHeader)
    }

    return 0.1
  }

  func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    if let question = self.question(indexPath), choice = self.choice(indexPath){

      if let choiceTuple = (self.selectedChoices[question.questionId]){

        if choiceTuple.indexPath != indexPath{
          tableView.deselectRowAtIndexPath(choiceTuple.indexPath, animated: true)
          self.selectedChoices[question.questionId] = (choice.choiceId, indexPath)
        }

      }else{
        self.selectedChoices[question.questionId] = (choice.choiceId, indexPath)
      }
    }
    updateActionButtonState()
  }
}


//
//  ProductViewController.swift
//  Engagement
//
//  Created by Microsoft on 17/02/2016.
//  Copyright Â© 2016 Microsoft. All rights reserved.
//

import UIKit

enum ProductViewType{
  case DataPush, Coupon

  var title: String{
    switch self{
    case .DataPush:
      return L10n.tr("product.discount.title")
    case .Coupon:
      return L10n.tr("product.title")
    }
  }
}

class ProductViewController: EngagementViewController {

  @IBOutlet weak var ibProductImage: UIImageView!
  @IBOutlet weak var ibProductName: UILabel!
  @IBOutlet weak var ibProductPrice: UILabel!
  @IBOutlet weak var ibRadioButton: UIButton!

  @IBOutlet weak var ibReductionButton: AzButton!

  var productViewType = ProductViewType.Coupon
  var discountApplied = false
  var discountRateInPercent = 0

  let formatter = NSNumberFormatter()

  init(productViewType : ProductViewType = .Coupon){
    super.init(nibName: nil, bundle: nil)
    self.productViewType = productViewType
  }

  required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
  }

  //MARK: Overriding
  override func engagementActivityName() -> String! {
    return AnalyticsMonitor.Activities.ProductDiscount
  }

  //MARK: View Life Cycle
  override func viewDidLoad() {
    super.viewDidLoad()

    NSNotificationCenter.defaultCenter().addObserver(self,
      selector: #selector(ProductViewController.getDataPushValues(_:)),
      name: Config.Notifications.dataPushValuesUpdated,
      object: nil)

    self.title = L10n.tr("product.discount.title")

    formatter.numberStyle = .CurrencyStyle
    let toto = NSLocalizedString("product.name", comment: "")
    ibProductName.text = toto //L10n.tr("product.name")

    ibReductionButton.setBackgroundImage(UIColor.imageWithColor(UIColor(named: UIColor.Name.LightGrey)),
      forState: .Highlighted)

    ibProductName.font = UIFont(named: UIFont.AppFont.Light, size: 35)
    ibProductPrice.font = UIFont(named: UIFont.AppFont.Regular, size: 30)
    ibRadioButton.setBackgroundImage(UIColor.imageWithColor(UIColor(named: UIColor.Name.SecondaryOrange)),
      forState: .Normal)
    ibReductionButton.titleLabel?.font = UIFont(named: UIFont.AppFont.Bold, size: 17)
    ibReductionButton.titleLabel?.numberOfLines = 0
    ibReductionButton.titleLabel?.lineBreakMode = .ByWordWrapping

    if self.productViewType == .Coupon {
      let attributed = NSMutableAttributedString(string: "20% off on your purchase\n",
        attributes: [NSFontAttributeName : UIFont(named: UIFont.AppFont.Bold, size: 16)])
      attributed.appendAttributedString(NSAttributedString(string: "Use coupon code 59AXCD when checking out",
        attributes: [NSFontAttributeName : UIFont(named: UIFont.AppFont.Medium, size: 13)]))
      self.ibRadioButton.contentMode = .Left
      self.ibRadioButton.setAttributedTitle(attributed, forState: .Normal)
    }
    getDataPushValues(nil)
  }

  func getDataPushValues(notification: NSNotification?) {
    let defaults = NSUserDefaults.standardUserDefaults()
    discountApplied = defaults.boolForKey(Config.Product.DataPush.isDiscountAvailable)
    if defaults.objectForKey(Config.Product.DataPush.discountRateInPercent) != nil {
      let discountRateInPercentValue = defaults.integerForKey(Config.Product.DataPush.discountRateInPercent)
      discountRateInPercent = discountRateInPercentValue < 0 ? 0 : discountRateInPercentValue > 100 ? 100 : discountRateInPercentValue
    } else {
      discountRateInPercent = Config.Product.defaultReductionRatio()
    }
    updatePriceButtonStyle()
  }

  //MARK: Actions
  @IBAction func didTapReductionButton(sender: AnyObject) {
    self.discountApplied = !self.discountApplied

    AnalyticsMonitor.sendActivityNamed(self.discountApplied ? AnalyticsMonitor.Events.ProductDiscount.applyDiscount : AnalyticsMonitor.Events.ProductDiscount.removeDiscount, extras: nil)

    if self.discountApplied == false {
      let defaults = NSUserDefaults.standardUserDefaults()
      defaults.removeObjectForKey(Config.Product.DataPush.isDiscountAvailable)
      defaults.removeObjectForKey(Config.Product.DataPush.discountRateInPercent)
      defaults.synchronize()
      getDataPushValues(nil)
    } else {
      updatePriceButtonStyle()
    }
  }

  //MARK: Private methods
  private func updatePriceButtonStyle() {

    if self.productViewType == .DataPush {
      ibRadioButton.hidden = !self.discountApplied
      let title = String(discountRateInPercent) + "% off"
      let attributed = NSAttributedString(string: title,
        attributes: [NSFontAttributeName : UIFont(named: UIFont.AppFont.Bold, size: 16)])
      self.ibRadioButton.contentMode = .Center
      self.ibRadioButton.setAttributedTitle(attributed, forState: .Normal)
    } else {
      ibRadioButton.hidden = false
      ibReductionButton.hidden = true
    }

    if discountApplied == true {
      ibReductionButton.setTitle(L10n.tr("product.discount.remove.discount.title"), forState: .Normal)
      ibReductionButton.setBackgroundImage(UIColor.imageWithColor(UIColor(named: UIColor.Name.SecondaryPurple)),
        forState: .Normal)

      let price = NSMutableAttributedString(string: formatter.stringFromNumber(Config.Product.defaultPrice)!,
        attributes: [NSForegroundColorAttributeName : UIColor(named: UIColor.Name.GeneralText),
          NSStrikethroughStyleAttributeName : NSNumber(integer: NSUnderlineStyle.StyleSingle.rawValue)])
      let newPrice = NSMutableAttributedString(string: " " + formatter.stringFromNumber(Config.Product.defaultPrice - (Config.Product.defaultPrice * discountRateInPercent / 100))!,
        attributes: [NSForegroundColorAttributeName : UIColor(named: UIColor.Name.SecondaryOrange)])

      price.appendAttributedString(newPrice)

      ibProductPrice.attributedText = price
    } else {
      ibReductionButton.setTitle(L10n.tr("product.discount.apply.discount.title"), forState: .Normal)
      ibReductionButton.setBackgroundImage(UIColor.imageWithColor(UIColor(named: UIColor.Name.SecondaryOrange)),
        forState: .Normal)
      let price = NSMutableAttributedString(string: formatter.stringFromNumber(Config.Product.defaultPrice)!,
        attributes: [NSForegroundColorAttributeName : UIColor(named: UIColor.Name.GeneralText)])
      ibProductPrice.attributedText = price
    }

  }

}


//
//  SuccessPollViewController.swift
//  Engagement
//
//  Created by Microsoft on 23/02/2016.
//  Copyright Â© 2016 Microsoft. All rights reserved.
//

import UIKit

/// SuccessPollViewController
class SuccessPollViewController: UIViewController {

  @IBOutlet weak var ibImageView: UIImageView!
  @IBOutlet weak var ibSuccessTitle: UILabel!
  @IBOutlet weak var ibCloseButton: AzButton!

  //MARK: View Life Cycle
  override func viewDidLoad() {
    super.viewDidLoad()

    self.view.backgroundColor = UIColor(named: UIColor.Name.PrimaryThemeLight)

    ibSuccessTitle.text = L10n.tr("new.poll.end.message")
    ibSuccessTitle.font = UIFont(named: UIFont.AppFont.Medium, size: 18)
    ibCloseButton.setBackgroundImage(UIColor.imageWithColor(UIColor(named: UIColor.Name.SecondaryPurple)), forState: .Normal)
    ibCloseButton.setTitle("Close", forState: .Normal)
    self.navigationItem.hidesBackButton = true
    self.title = L10n.tr("new.poll.title")
    // Do any additional setup after loading the view.
  }

  //MARK: Actions
  @IBAction func didTapCloseButton(sender: AnyObject) {
    self.dismissViewControllerAnimated(true, completion: nil)
  }

}


//
//  VideosViewController.swift
//  Engagement
//
//  Created by Microsoft on 11/02/2016.
//  Copyright Â© 2016 Microsoft. All rights reserved.
//

import UIKit
import AVFoundation
import AVKit

/// Display the AZME videos SDK presentations
class VideosViewController: CenterViewController {

  @IBOutlet weak var ibTableView: UITableView!

  var dataSource = [Video]()

  var videoJobStarted = false

  //MARK: Overriding
  override func engagementActivityName() -> String! {
    return AnalyticsMonitor.Activities.Videos
  }

  //MARK: View Life Cycle
  override func viewDidLoad() {
    super.viewDidLoad()

    self.title = L10n.tr("menu.videos.title")

    ibTableView.backgroundColor = UIColor(named: UIColor.Name.SecondaryGrey)
    ibTableView.separatorStyle = .None
    ibTableView.rowHeight = UITableViewAutomaticDimension
    ibTableView.estimatedRowHeight = 100
    ibTableView.registerNib(UINib(nibName: VideoCell.identifier, bundle: nil),
      forCellReuseIdentifier: VideoCell.identifier)

    self.reloadData()
  }

  override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)

    UIApplication.sharedApplication().setStatusBarHidden(false, withAnimation: .Fade)
    if videoJobStarted == true {
      AnalyticsMonitor.Jobs.Video.end()
    }
  }

  /**
   Fetch video data
   */
  private func reloadData(){
    //Load video feed
    UIApplication.showHUD()
    AzMEService.fetchAzMEVideoFeed { (videos, error) -> Void in
      self.dataSource = videos

      self.ibTableView.reloadData()
      UIApplication.dismissHUD()
    }
  }

}

//MARK: UITableViewDataSource
extension VideosViewController: UITableViewDataSource {
  func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return self.dataSource.count > 0 ? 1 : 0
  }

  func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return self.dataSource.count
  }

  func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier(VideoCell.identifier, forIndexPath: indexPath) as! VideoCell

    let video = self.dataSource[indexPath.row]
    cell.updateWith(video.title, subTitle: video.description, imageLink: video.pictureUrl, localImage: video.isEmbed)

    return cell
  }
}

//MARK: UITableViewDelegate
extension VideosViewController: UITableViewDelegate {

  func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    let video = self.dataSource[indexPath.row]

    if let videoUrl = video.videoUrl, videoURL = NSURL(string: videoUrl){
      let playerController = AVPlayerViewController()
      playerController.delegate = self
      if video.isEmbed == true{
        if let videoURLEmbed = NSBundle.mainBundle().URLForResource(videoUrl, withExtension: ".mp4"){
          playerController.player = AVPlayer(URL: videoURLEmbed)
        }
      }else{

        playerController.player = AVPlayer(URL: videoURL)
      }
      //AnalyticsMonitor.sendActivityNamed(AnalyticsMonitor.Events.Video, extras: [NSObject : AnyObject]?)
      UIApplication.sharedApplication().setStatusBarHidden(true, withAnimation: .Fade)

      self.navigationController?.presentViewController(playerController,
        animated: true,
        completion: { [unowned self] in
          self.ibTableView.deselectRowAtIndexPath(indexPath, animated: true)
          playerController.player!.play()
          AnalyticsMonitor.sendActivityNamed(AnalyticsMonitor.Events.Video.play, extras: nil)
          AnalyticsMonitor.Jobs.Video.start(video.title, URL: videoUrl)
          self.videoJobStarted = true
        })
    }

  }
}

extension VideosViewController: AVPlayerViewControllerDelegate {
  //TODO : Video tagging
}


//
//  AzMESafariController.swift
//  Engagement
//
//  Created by Microsoft on 10/02/2016.
//  Copyright Â© 2016 Microsoft. All rights reserved.
//

import UIKit
import SafariServices

/// Simple Overriding of the SFSafariViewController controller class, to customize UI elements
class AzMESafariController: SFSafariViewController {

  override func viewDidLoad() {
    super.viewDidLoad()
    self.view.tintColor = UIColor(named: UIColor.Name.PrimaryTheme)

  }
}


//
//  WebViewController.swift
//  Engagement
//
//  Created by Microsoft on 12/02/2016.
//  Copyright Â© 2016 Microsoft. All rights reserved.
//

import UIKit

/// Simple WebViewController
class WebViewController: CenterViewController {

  @IBOutlet weak var ibActivityIndicator: UIActivityIndicatorView!
  @IBOutlet weak var ibWebView: UIWebView!

  var URL: NSURL?
  var navTitle: String?

  //MARK: Initialization
  convenience init() {
    self.init(title: "", URL: nil)
  }

  init(title: String?, URL: NSURL?){
    super.init(nibName: nil, bundle: nil)
    self.URL = URL
    self.navTitle = title
  }

  init(howToNotificationType: ScreenType)
  {
    super.init(nibName: nil, bundle: nil)

    if let ressourceName = howToNotificationType.howToRessourcePathName,
      url = NSBundle.mainBundle().pathForResource(ressourceName,
        ofType: "html",
        inDirectory: Config.defaultHTMLHowToDir)
    {
      self.URL = NSURL(fileURLWithPath: url)
    }
    self.navTitle = howToNotificationType.howTitle
  }

  required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
  }

  //MARK: View Life Cycle
  override func viewDidLoad() {
    super.viewDidLoad()

    self.title = navTitle

    if let URL = self.URL{
      self.ibWebView.loadRequest(NSURLRequest(URL: URL))
    }
  }

  //MARK: Overriding
  override func engagementActivityName() -> String! {
    if (self.URL?.absoluteString == Config.URLs.features){
      return AnalyticsMonitor.Activities.Features
    }
    else{
      return "WebViewController"
    }
  }
}

//MARK: UIWebViewDelegate
extension WebViewController: UIWebViewDelegate {

  func webViewDidStartLoad(webView: UIWebView) {
    self.ibActivityIndicator.startAnimating()
  }

  func webViewDidFinishLoad(webView: UIWebView) {
    self.ibActivityIndicator.stopAnimating()
  }

  func webView(webView: UIWebView, didFailLoadWithError error: NSError?) {
    self.ibActivityIndicator.stopAnimating()
  }

}


//
//  RecentUpdate.swift
//  Engagement
//
//  Created by Microsoft on 12/02/2016.
//  Copyright Â© 2016 Microsoft. All rights reserved.
//

import Foundation
import SWXMLHash

/// Recent Update model
class RecentUpdate {

  var title: String?
  var description: String?
  var pubDate: String?
  var link: String?
  var category: String?

  /**
   Parse a XML element to create a RecentUpdate Object

   - parameter element: XMLIndexer element

   - returns: RecentUpdate object
   */
  static func parseFromXMLElements(element: XMLIndexer) -> RecentUpdate
  {
    let recentUpdate = RecentUpdate()
    recentUpdate.title = element["title"].element?.text
    recentUpdate.pubDate = element["pubDate"].element?.text

    if let text = element["description"].element?.text
    {
      //decode text
      let encodedData = text.dataUsingEncoding(NSUTF8StringEncoding)!

      let text = try! NSAttributedString(data: encodedData, options: [NSDocumentTypeDocumentAttribute:NSHTMLTextDocumentType,
        NSCharacterEncodingDocumentAttribute:NSUTF8StringEncoding], documentAttributes: nil)

      let cleanedText = text.string.stringByReplacingOccurrencesOfString("<[^>]+>", withString: "", options: .RegularExpressionSearch, range: nil)
      recentUpdate.description = cleanedText

    }

    recentUpdate.link = element["link"].element?.text
    recentUpdate.category = element["category"].element?.text
    return recentUpdate
  }
}


//
//  Video.swift
//  Engagement
//
//  Created by Microsoft on 09/02/2016.
//  Copyright Â© 2016 Microsoft. All rights reserved.
//

import Foundation
import SwiftyJSON

/**
 *  Video struct model
 */
struct Video {

  var title: String?
  var description: String?
  var pictureUrl: String?
  var videoUrl: String?
  var isEmbed = false

  static func parseFromJSONElement(json: JSON) -> Video
  {
    var video = Video()
    video.title = json["title"].stringValue
    video.pictureUrl = json["pictureUrl"].stringValue
    video.description = json["description"].stringValue
    video.videoUrl = json["videoUrl"].stringValue
    return video
  }

  /**
   Default embed video

   - returns: a Video model pointing on a local video
   */
  static func defaultVideo() -> Video
  {
    return Video(title: "Azure Mobile Engagement Overview",
      description: "Brief overview of Azure Mobile Engagement service and the benefits it provides to the app publishers/marketers",
      pictureUrl: "mobileengagementoverview_960",
      videoUrl: "mobileengagementoverview_mid",
      isEmbed: true)
  }
}


//
//  AnnouncementViewModel.swift
//  Engagement
//
//  Created by Microsoft on 18/02/2016.
//  Copyright Â© 2016 Microsoft. All rights reserved.
//

import Foundation

/**
 *  Represent an announcement ViewModel
 It offers the possibility to regroup Azure and Fake Local announcement inside one repressentation
 It can be created via an Azure Reach Announcement
 */
struct AnnouncementViewModel {

  var title: String?
  var actionTitle: String?
  var exitTitle: String?
  var body: String?
  var URL: NSURL?
  var type = AEAnnouncementType.Unknown

  var action: (() -> Void)?

  init(){}

  /**
   Init the ViewModel with an AEReachAnnouncement Model

   - parameter announcement: Azure Announcement

   - returns: an AnnouncementViewModel
   */
  init(fromAnnouncement announcement: AEReachAnnouncement){
    self.title = announcement.title
    self.actionTitle = announcement.actionLabel
    self.exitTitle = announcement.exitLabel
    self.body = announcement.body
    self.type = announcement.type
  }
}


//
//  HomeDataSource.swift
//  Engagement
//
//  Created by Microsoft on 23/02/2016.
//  Copyright Â© 2016 Microsoft. All rights reserved.
//

import Foundation

//MARK: Data Source Structs
struct HomeSection{
  var title: String
  var titleColor: UIColor
  var bgColor: UIColor
  var buttonTitle: String
  var action: (() -> Void)?
}

/**
 *  Home Data Source structure, contains default highlited elements
 */
struct HomeDataSource {
  var highlights = [L10n.tr("home.hightlight.1"),
    L10n.tr("home.hightlight.2"),
    L10n.tr("home.hightlight.3"),
    L10n.tr("home.hightlight.4"),
    L10n.tr("home.hightlight.5"),
    L10n.tr("home.hightlight.6"),
    L10n.tr("home.hightlight.7")]

  let sectionHighlights = HomeSection(title: L10n.tr("home.hightlight.title"),
    titleColor: .whiteColor(),
    bgColor: UIColor(named: UIColor.Name.SecondaryOrange),
    buttonTitle: "",
    action: nil)

  var sections = [(section: HomeSection, items: [AnyObject])]()

  init(){
    sections.append((self.sectionHighlights, self.highlights))
  }
}