/**
 * Copyright (c) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License. See License.txt in the project root for
 * license information.
 */

import Foundation

public class CoderFactory {
    public static func encoder(for mimeType: MimeType) throws -> AzureEncoder {
        switch(mimeType) {
            case .json:
                return AzureJSONEncoder()
            case .xml:
                return PropertyListEncoder()
            case .gif, .jpeg, .png:
                return ImageEncoder()
            default:
                throw RuntimeError.general(message: "Decoder for \(mimeType) not found.")
        }
    }

    public static func decoder(for mimeType: MimeType) throws -> AzureDecoder {
        switch(mimeType) {
            case .json:
                return AzureJSONDecoder();
            case .xml:
//                let dateFormatter = DateFormatter()
//                dateFormatter.dateFormat = "EEE, dd MMM yyyy HH:mm:ssZ"
                let xmlDecoder = XMLDecoder()
//                xmlDecoder.dateDecodingStrategy = .formatted(dateFormatter)
                return xmlDecoder
            default:
                throw RuntimeError.general(message: "Decoder for \(mimeType) not found.")
        }
    }
}

extension XMLDecoder : AzureDecoder {
}

public protocol PageDecoder {
    var isPagedData: Bool { get set }
    var nextLinkName: String? {get set }
    var nextLink: String? { get set }
}

public protocol AzureEncoder {
    func encode<T>(_ value: T?) throws -> Data where T : Encodable
}

public protocol AzureDecoder {
    func decode<T>(_ type: T.Type, from data: Data) throws -> T where T : Decodable
}

extension AzureJSONEncoder : AzureEncoder {
}

extension PropertyListEncoder : AzureEncoder {
}

extension AzureJSONDecoder : AzureDecoder {
}

public class AzureXMLDecocder : PropertyListDecoder, AzureDecoder, PageDecoder {
    public var isPagedData = false
    public var nextLinkName: String?
    public var nextLink: String?
}

public struct UnknownCodingKey: CodingKey {
    public init?(stringValue: String) { self.stringValue = stringValue }
    public let stringValue: String

    public init?(intValue: Int) { return nil }
    public var intValue: Int? { return nil }

    public static func decodeStringForKey(decoder: Decoder, keyForDecode: String?) throws -> String? {
        if keyForDecode == nil {
            return nil;
        }

        let container = try decoder.container(keyedBy: UnknownCodingKey.self)
        var retVal: String? = nil;
        for key in container.allKeys {
            if key.stringValue != keyForDecode {
                continue;
            }

            func decodeUnknownValue<T: Decodable>(_ type: T.Type) -> T? {
                guard let value = try? container.decode(type, forKey: key) else {
                    return nil
                }

                return value
            }

            retVal = decodeUnknownValue(String.self)
            break;

        }

        return retVal;
    }
}


/**
 * Copyright (c) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License. See License.txt in the project root for
 * license information.
 */

import Foundation

public struct DataWrapper : Decodable {
    public let data: Data;

    public init(data: Data) {
        self.data = data as Data;
    }

    public init(from decoder: Decoder) throws {
        self.data = Data()
    }
}


/**
 * Copyright (c) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License. See License.txt in the project root for
 * license information.
 */

import Foundation

public enum DateFormat: String {
    case rfc1123 = "EEE, dd MMM yyyy HH:mm:ssZ"
    case iso8601DateTime = "yyyy-MM-dd'T'HH:mm:ssZ"
    case iso8601DateTimeMs = "yyyy-MM-dd'T'HH:mm:ss.SSZ"
    case iso8601Date = "yyyy-MM-dd"
}

public enum AzureDateFormat : String {
    case dateTimeRfc1123 = "date-time-rfc1123"
    case dateTime = "date-time"
    case date = "date"

    public func toFormatString() -> String {
        switch self {
        case .dateTimeRfc1123:
            return DateFormat.rfc1123.rawValue
        case .dateTime:
            return DateFormat.iso8601DateTime.rawValue
        case .date:
            return DateFormat.iso8601Date.rawValue
        }
    }

    public func toString(date: Date, timezone: TimeZone? = TimeZone(identifier: "GMT")) -> String {
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = self.toFormatString()
        dateFormatter.timeZone = timezone
        return dateFormatter.string(from: date)
    }

    public func toDate(dateStr: String) -> Date? {
        let dateFormatter = DateFormatter()
        switch self {
        case .dateTime:
            if dateStr.range(of: ".") == nil {
                dateFormatter.dateFormat = DateFormat.iso8601DateTime.rawValue
            } else {
                dateFormatter.dateFormat = DateFormat.iso8601DateTimeMs.rawValue
            }
        default:
            dateFormatter.dateFormat = self.toFormatString()
        }

        return dateFormatter.date(from: dateStr)
    }
}

public class DateConverter {

    static public func toString(date: Date?, format: AzureDateFormat) -> String? {
        guard let _ = date else {
            return nil
        }
        return format.toString(date: date!)
    }

    static public func fromString(dateStr: String?, format: AzureDateFormat) -> Date? {
        guard let _ = dateStr else {
            return nil
        }
        return Date(fromString: dateStr!, format: format)
    }
}

public extension Date {
    public init?(fromString: String, format: AzureDateFormat) {
        let dateStr = fromString.uppercased()
        if let date = format.toDate(dateStr: dateStr) {
            self = date
        } else {
            return nil
        }
    }
}


/**
 * Copyright (c) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License. See License.txt in the project root for
 * license information.
 */

import Foundation

public enum Endpoint: String {
    case portal                         = "portalUrl"
    case management                     = "managementEndpointUrl"
    case resourceManager                = "resourceManagerEndpointUrl"
    case activeDirectory                = "activeDirectoryEndpointUrl"
    case graph                          = "activeDirectoryGraphResourceId"
    case keyVault                       = "keyVaultDnsSuffix"
    case storage                        = "storageEndpointSuffix"
    case dataLakeStore                  = "azureDataLakeStoreFileSystemEndpointSuffix"
    case dataLakeAnalystic              = "azureDataLakeAnalyticsCatalogAndJobEndpointSuffix"
    case gallery                        = "galleryEndpointUrl"
    case sql                            = "sqlManagementEndpointUrl"
    case dataLake                       = "dataLakeEndpointResourceId"
    case publishingProfile              = "publishingProfileUrl"
    case sqlServerHostnameSuffix        = "sqlServerHostnameSuffix"
    case activeDirectoryResourceId      = "activeDirectoryResourceId"
    case activeDirectoryGraphApiVersion = "activeDirectoryGraphApiVersion"
}


/**
 * Copyright (c) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License. See License.txt in the project root for
 * license information.
 */

import Foundation

public protocol Environment {
    var endpoints : Dictionary<Endpoint, String> { get }
    func url(forEndpoint: Endpoint) -> String?
}

public class AuzureEnvironment : Environment {
    public let endpoints : Dictionary<Endpoint, String>

    public init(endpoints : Dictionary<Endpoint, String>) {
        self.endpoints = endpoints
    }

    public func url(forEndpoint: Endpoint) -> String? {
        return self.endpoints[forEndpoint]
    }

    static let azure = AuzureEnvironment(endpoints: [
        .management             : "https://management.core.windows.net",
        .resourceManager        : "https://management.azure.com/",
        .graph                  : "https://graph.windows.net/",
        .activeDirectory        : "https://login.microsoftonline.com/",
        .keyVault               : ".vault.azure.net",
        .storage                : ".core.windows.net",
        .dataLakeStore          : "azuredatalakestore.net",
        .dataLakeAnalystic      : "azuredatalakeanalytics.net",
        .gallery                : "https://gallery.azure.com/",
        .sql                    : "https://management.core.windows.net:8443/",
        .dataLake               : "https://datalake.azure.net/",
        .portal                 : "http://go.microsoft.com/fwlink/?LinkId=254433",
        .publishingProfile      : "http://go.microsoft.com/fwlink/?LinkId=254432",
        .sqlServerHostnameSuffix        : ".database.windows.net",
        .activeDirectoryResourceId      : "https://management.core.windows.net/",
        .activeDirectoryGraphApiVersion : "2013-04-05",
    ])
}


//
//  MapDecoder.swift
//  azureSwiftRuntime
//
//  Created by Vladimir Shcherbakov on 1/25/18.
//

import Foundation

open class HeadersDecoder: XMLDecoder {
    open func decode<T : Decodable>(_ type: T.Type, from headers: [String:String]) throws -> T {
        let decoder = _XMLDecoder(referencing: headers, options: self.options)
        return try T(from: decoder)
    }
}


/**
 * Copyright (c) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License. See License.txt in the project root for
 * license information.
 */

import Foundation

public class ImageEncoder : AzureEncoder {
    public func encode<T>(_ value: T) throws -> Data where T : Encodable {
        return Data();
    }
}


/**
 * Copyright (c) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License. See License.txt in the project root for
 * license information.
 */

import Foundation

public class LogInterceptor {

    func prefix() -> String {
        return ""
    }

    func printUrl(url: String) {
        if self.showOptions.contains(LogInterceptor.Show.all)
            || self.showOptions.contains(LogInterceptor.Show.url) {
            print(prefix(), url)
        }
    }

    func printHeaders(headers:[String:String]?) {
        if self.showOptions.contains(LogInterceptor.Show.all)
            || self.showOptions.contains(LogInterceptor.Show.headers) {
            if let h = headers {
                for (key, value) in h {
                    if headersToHide.isEmpty || !headersToHide.contains(key.uppercased()) {
                        if headersToShow.isEmpty || headersToShow.contains(key.uppercased()) {
                            print(prefix(), "[\(key)] = \(value)")
                        }
                    }
                }
            }
        }
    }

    func printBody(body: Data?) {
        if self.showOptions.contains(LogInterceptor.Show.all)
            || self.showOptions.contains(LogInterceptor.Show.body) {
            if let b = body {
                if b.count > 0 && b.count < 1024 {
                    if let bodyAsString = String(data: b, encoding: .utf8) {
                        if (!bodyAsString.isEmpty) {
                            print(prefix(), bodyAsString)
                        }
                    }
                } else {
                    print(prefix(), b)
                }
            }
        }
    }

    private var headersToShow = [String]()

    public func withHeadersToShow(_ headersToShow: [String]) -> Self {
        self.headersToShow = headersToShow.map{$0.uppercased()}
        return self
    }

    private var headersToHide = [String]()

    public func withHeadersToHide(_ headersToHide: [String]) -> Self {
        self.headersToHide = headersToHide.map{$0.uppercased()}
        return self
    }

    public enum Show {
        case url
        case headers
        case body
        case all
    }

    private var showOptions: Set<Show> = Set([.all])

    public init(showOptions: [Show]) {
        self.showOptions = Set(showOptions)
    }
}


/**
 * Copyright (c) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License. See License.txt in the project root for
 * license information.
 */

import Foundation

public enum MimeType : String {
    case json = "application/json"
    case xml = "application/xml"
    case plain = "text/plain"
    case png = "image/png"
    case jpeg = "image/jpeg"
    case gif = "image/gif"
    case unknown = "unknown"

    public static func getType(forStr: String) -> MimeType? {
        let mimeType = MimeType.init(rawValue: forStr);
        return mimeType
    }
}


/**
 * Copyright (c) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License. See License.txt in the project root for
 * license information.
 */

import Foundation

public protocol RequestInterceptor {
    func intercept(url: inout String, method: inout String, headers: inout [String:String]?, body: inout Data?) -> Void
}

public class CustomHeadersInterceptor : RequestInterceptor {

    let customHeaders:[String:String]

    public init(customHeaders: [String:String]) {
        self.customHeaders = customHeaders
    }

    public func intercept(url: inout String, method: inout String, headers: inout [String : String]?, body: inout Data?) {

        if headers == nil {
            headers = [:]
        }
        for (key, value) in self.customHeaders {
            headers![key] = value
        }
    }
}

public class AuthHeaderInterceptor : RequestInterceptor {

    let atc: AzureTokenCredentials

    public init(atc: AzureTokenCredentials) {
        self.atc = atc
    }

    public func intercept(url: inout String, method: inout String, headers: inout [String : String]?, body: inout Data?) {
        if headers == nil {
            headers = [:]
        }

        headers!["Authorization"] = try? atc.authHeaderValue(url: nil)
    }
}

public class LogRequestInterceptor : LogInterceptor, RequestInterceptor {
    override public init(showOptions: Show...) {
        super.init(showOptions: showOptions)
    }

    public func intercept(url: inout String, method: inout String, headers: inout [String : String]?, body: inout Data?) {
        printUrl(url: "\(method) \(url)")
        printHeaders(headers: headers)
        printBody(body: body)
    }

    override func prefix() -> String {
        return "<--"
    }

}


/**
 * Copyright (c) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License. See License.txt in the project root for
 * license information.
 */

import Foundation

public protocol ResponseInterceptor {
    func intercept(httpResponse: inout HTTPURLResponse, data: inout Data?) -> Void
}

public class LogResponseInterceptor : LogInterceptor, ResponseInterceptor {
    override public init(showOptions: Show...) {
        super.init(showOptions: showOptions)
    }

    public func intercept(httpResponse: inout HTTPURLResponse, data: inout Data?) {
        let url = httpResponse.url?.absoluteString ?? "Url is nil"
        //let url = ""
        printUrl(url: "\(httpResponse.statusCode) \(url)")
        printHeaders(headers: httpResponse.allHeaderFields as? [String:String])
        printBody(body: data)
    }

    override func prefix() -> String {
        return "-->\t"
    }
}


/**
 * Copyright (c) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License. See License.txt in the project root for
 * license information.
 */

import Foundation
import RxSwift

public protocol RuntimeClient {
    func executeAsync<T>(command: BaseCommand) -> Observable<T?> where T : Decodable

    // non-blocking
    func executeAsync<T>(command: BaseCommand, completionHandler: @escaping (T?, Error?)->Void) where T : Decodable

    // non-blocking, no return value - just error
    func executeAsync(command: BaseCommand, completionHandler: @escaping (Error?)->Void)

    // long-running
    func executeAsyncLRO<T>(command: BaseCommand, completionHandler: @escaping (T?, Error?)->Void) where T : Decodable

    // long-running, no return value - just error
    func executeAsyncLRO(command: BaseCommand, completionHandler: @escaping (Error?)->Void)

    // blocking
    func execute(command: BaseCommand) throws -> Decodable?
}


/**
 * Copyright (c) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License. See License.txt in the project root for
 * license information.
 */

import Foundation

public enum RuntimeError: Error {
    case general(message: String)
    case operationFailed
    case operationCanceled
    case errorStatusCode(code: Int, data: Data)
    case invalidData
}

public struct CloudError: Codable {
    public let status: Int?
    public let message: String?
}


/**
 * Copyright (c) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License. See License.txt in the project root for
 * license information.
 */

import Foundation

protocol ServiceClientCredential {
    func authHeaderValue(url: String?) throws -> String
}


/**
 * Copyright (c) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License. See License.txt in the project root for
 * license information.
 */

import Foundation

protocol TokenCredentials: ServiceClientCredential {
    func getToken(forResource: String) throws -> String
}


//
//  XMLDecoder.swift
//  azureSwiftRuntime
//
//  Created by Vladimir Shcherbakov on 1/11/18.
//

import Foundation

open class XMLDecoder {

    // MARK: Options

    /// The strategy to use for decoding `Date` values.
    public enum DateDecodingStrategy {
        /// Defer to `Date` for decoding. This is the default strategy.
        case deferredToDate

        /// Decode the `Date` as a UNIX timestamp from a XML number.
        case secondsSince1970

        /// Decode the `Date` as UNIX millisecond timestamp from a XML number.
        case millisecondsSince1970

        /// Decode the `Date` as an ISO-8601-formatted string (in RFC 3339 format).
        @available(OSX 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
        case iso8601

        /// Decode the `Date` as a string parsed by the given formatter.
        case formatted(DateFormatter)

        /// Decode the `Date` as a custom value decoded by the given closure.
        case custom((_ decoder: Decoder) throws -> Date)
    }

    /// The strategy to use for decoding `Data` values.
    public enum DataDecodingStrategy {
        /// Defer to `Data` for decoding.
        case deferredToData

        /// Decode the `Data` from a Base64-encoded string. This is the default strategy.
        case base64

        /// Decode the `Data` as a custom value decoded by the given closure.
        case custom((_ decoder: Decoder) throws -> Data)
    }

    /// The strategy to use for non-XML-conforming floating-point values (IEEE 754 infinity and NaN).
    public enum NonConformingFloatDecodingStrategy {
        /// Throw upon encountering non-conforming values. This is the default strategy.
        case `throw`

        /// Decode the values from the given representation strings.
        case convertFromString(positiveInfinity: String, negativeInfinity: String, nan: String)
    }

    private static var defaultDecodingStrategy : DateDecodingStrategy {
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "EEE, dd MMM yyyy HH:mm:ssZ"
        return .formatted(dateFormatter)
    }

    /// The strategy to use in decoding dates. Defaults to `.deferredToDate`.
    //open var dateDecodingStrategy: DateDecodingStrategy = .deferredToDate
    open var dateDecodingStrategy: DateDecodingStrategy = defaultDecodingStrategy

    /// The strategy to use in decoding binary data. Defaults to `.base64`.
    open var dataDecodingStrategy: DataDecodingStrategy = .base64

    /// The strategy to use in decoding non-conforming numbers. Defaults to `.throw`.
    open var nonConformingFloatDecodingStrategy: NonConformingFloatDecodingStrategy = .throw

    /// Contextual user-provided information for use during decoding.
    open var userInfo: [CodingUserInfoKey : Any] = [:]

    /// Options set on the top-level encoder to pass down the decoding hierarchy.
    internal struct _Options {
        let dateDecodingStrategy: DateDecodingStrategy
        let dataDecodingStrategy: DataDecodingStrategy
        let nonConformingFloatDecodingStrategy: NonConformingFloatDecodingStrategy
        let userInfo: [CodingUserInfoKey : Any]
    }

    /// The options set on the top-level decoder.
    internal var options: _Options {
        return _Options(dateDecodingStrategy: dateDecodingStrategy,
                        dataDecodingStrategy: dataDecodingStrategy,
                        nonConformingFloatDecodingStrategy: nonConformingFloatDecodingStrategy,
                        userInfo: userInfo)
    }

    // MARK: - Constructing a XML Decoder

    /// Initializes `self` with default strategies.
    public init() {}

    // MARK: - Decoding Values

    /// Decodes a top-level value of the given type from the given XML representation.
    ///
    /// - parameter type: The type of the value to decode.
    /// - parameter data: The data to decode from.
    /// - returns: A value of the requested type.
    /// - throws: `DecodingError.dataCorrupted` if values requested from the payload are corrupted, or if the given data is not valid XML.
    /// - throws: An error if any value throws an error during decoding.
    open func decode<T : Decodable>(_ type: T.Type, from data: Data) throws -> T {
        let topLevel = try XMLSerialization.xmlObject(data: data)
        let decoder = _XMLDecoder(referencing: topLevel, options: self.options)
        return try T(from: decoder)
    }

    open func withDateFormatString(_ dateFormatString: String) -> XMLDecoder {
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = dateFormatString
        self.dateDecodingStrategy = .formatted(dateFormatter)
        return self
    }
}

//===----------------------------------------------------------------------===//
// Shared Key Types
//===----------------------------------------------------------------------===//

internal struct _XMLKey : CodingKey {
    public var stringValue: String
    public var intValue: Int?

    public init?(stringValue: String) {
        self.stringValue = stringValue
        self.intValue = nil
    }

    public init?(intValue: Int) {
        self.stringValue = "\(intValue)"
        self.intValue = intValue
    }

    internal init(index: Int) {
        self.stringValue = "Index \(index)"
        self.intValue = index
    }

    internal static let `super` = _XMLKey(stringValue: "super")!
}

//===----------------------------------------------------------------------===//
// Shared ISO8601 Date Formatter
//===----------------------------------------------------------------------===//

// NOTE: This value is implicitly lazy and _must_ be lazy. We're compiled against the latest SDK (w/ ISO8601DateFormatter), but linked against whichever Foundation the user has. ISO8601DateFormatter might not exist, so we better not hit this code path on an older OS.
@available(OSX 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
internal var _iso8601Formatter: ISO8601DateFormatter = {
    let formatter = ISO8601DateFormatter()
    formatter.formatOptions = .withInternetDateTime
    return formatter
}()


//
//  XMLDecodingError.swift
//  azureSwiftRuntime
//
//  Created by Vladimir Shcherbakov on 1/17/18.
//

import Foundation

enum XMLDecodingError : Error {
    case keyDuplicates
}

internal extension DecodingError {
    /// Returns a `.typeMismatch` error describing the expected type.
    ///
    /// - parameter path: The path of `CodingKey`s taken to decode a value of this type.
    /// - parameter expectation: The type expected to be encountered.
    /// - parameter reality: The value that was encountered instead of the expected type.
    /// - returns: A `DecodingError` with the appropriate path and debug description.
    internal static func _typeMismatch(at path: [CodingKey], expectation: Any.Type, reality: Any) -> DecodingError {
        let description = "Expected to decode \(expectation) but found \(_typeDescription(of: reality)) instead."
        return .typeMismatch(expectation, Context(codingPath: path, debugDescription: description))
    }

    /// Returns a description of the type of `value` appropriate for an error message.
    ///
    /// - parameter value: The value whose type to describe.
    /// - returns: A string describing `value`.
    /// - precondition: `value` is one of the types below.
    fileprivate static func _typeDescription(of value: Any) -> String {
        if value is NSNull {
            return "a null value"
        } else if value is NSNumber /* FIXME: If swift-corelibs-foundation isn't updated to use NSNumber, this check will be necessary: || value is Int || value is Double */ {
            return "a number"
        } else if value is String {
            return "a string/data"
        } else if value is [Any] {
            return "an array"
        } else if value is [String : Any] {
            return "a dictionary"
        } else {
            // This should never happen -- we somehow have a non-JSON type here.
            preconditionFailure("Invalid storage type \(type(of: value)).")
        }
    }
}


//
//  XMLSerialization.swift
//  azureSwiftRuntime
//
//  Created by Vladimir Shcherbakov on 1/12/18.
//

import Foundation

open class XMLSerialization {
    public static func xmlObject(data: Data) throws -> Any {
        return try _XMLParser(xmlData: data).parseXML()
    }
}

fileprivate class Node {
    var children = [Node]()
    var value: Any = NSNull()
    var name: String

    init (name: String) {
        self.name = name
    }

    func printTree(level: Int = 0) {
        let tabs = String(repeating: "\t", count: level)
        print(tabs, name, value is NSNull ? "" : value)
        for child in children {
            child.printTree(level: level+1)
        }
    }

    func convertTree() throws -> (String, Any) {
        if children.isEmpty {
            return (name, value as Any)
        } else {
            var chPairList = [(String, Any)]()
            for child in children {
                let chPair = try child.convertTree()
                chPairList.append(chPair)
            }

            let mapOrArray = try buildMapOrArray(pairList: chPairList)
            return (name, mapOrArray)
        }
    }

    private func buildMapOrArray(pairList: [(String, Any)]) throws -> Any {
        if pairList.count == 1 {
            let (key, val) = pairList.first!
            return [key:val]
        }

        var testMap = [String:[Any]]()
        for pair in pairList {
            let (key, val) = pair
            if var values = testMap[key] {
                values.append(val)
                testMap[key] = values
            } else {
                testMap[key] = [val]
            }
        }

        switch testMap.count {
        case 1: // array
            let (_, values) = testMap.first!
            return values
        case pairList.count: // map
            var map = [String:Any]()
            for pair in pairList {
                let (key, val) = pair
                map[key] = val
            }

            return map
        default: // error
            throw XMLDecodingError.keyDuplicates
        }
    }
}

fileprivate struct Stack<T> {
    private var array: [T] = []

    mutating func push(_ element: T) {
        array.append(element)
    }

    mutating func pop() -> T? {
        return array.popLast()
    }

    func peek() -> T? {
        return array.last
    }
}

fileprivate class _XMLParser: NSObject, XMLParserDelegate {
    var parser: XMLParser

    var stack = Stack<Node>()

    var errors = [Error]()

    var root = Node(name: "Root")

    init(xmlData: Data) {
        parser = XMLParser(data: xmlData)
        super.init()
        parser.delegate = self
    }

    func parseXML() throws -> Any {
        parser.parse()
        //root.printTree()
        if !errors.isEmpty {
            throw errors.first!
        }

        let (_, val) = try root.convertTree()

        //return [key: val]
        return val
    }

    func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) {
        //print("-->", elementName)

        let newNode = Node(name: elementName)
        if !attributeDict.isEmpty {
            for (key, val) in attributeDict {
                let attrNode = Node(name: key)
                attrNode.value = val
                newNode.children.append(attrNode)
            }
        }
        if let node = stack.pop() {
            node.children.append(newNode)
            stack.push(node)
            stack.push(newNode)
        } else {
            root = newNode
            stack.push(root)
        }
    }

    func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
        //print("<--", elementName)
        if let node = stack.pop() {
            if node.name != elementName {
                print("!!! Parser Error", "pop elem is not equal end elem" )
            }
        }
    }

    func parser(_ parser: XMLParser, foundCharacters string: String) {
        //print("\t", string)
        if let node = stack.pop() {
            let val = (node.value is NSNull) ? "" : node.value as! String
            node.value = val + string.trimmingCharacters(in: .whitespacesAndNewlines)
            stack.push(node)
        }
    }

    func parser(_ parser: XMLParser, parseErrorOccurred parseError: Error) {
        print("!!!", parseError)
        errors.append(parseError)
    }
}


//
//  _XMLDecoder.swift
//  azureSwiftRuntime
//
//  Created by Vladimir Shcherbakov on 1/17/18.
//

import Foundation

internal class _XMLDecoder : Decoder {
    // MARK: Properties

    /// The decoder's storage.
    internal var storage: _XMLDecodingStorage

    /// Options set on the top-level decoder.
    internal let options: XMLDecoder._Options

    /// The path to the current point in encoding.
    private(set) public var codingPath: [CodingKey]

    /// Contextual user-provided information for use during encoding.
    public var userInfo: [CodingUserInfoKey : Any] {
        return self.options.userInfo
    }

    // MARK: - Initialization

    /// Initializes `self` with the given top-level container and options.
    internal init(referencing container: Any, at codingPath: [CodingKey] = [], options: XMLDecoder._Options) {
        self.storage = _XMLDecodingStorage()
        self.storage.push(container: container)
        self.codingPath = codingPath
        self.options = options
    }

    // MARK: - Coding Path Operations

    /// Performs the given closure with the given key pushed onto the end of the current coding path.
    ///
    /// - parameter key: The key to push. May be nil for unkeyed containers.
    /// - parameter work: The work to perform with the key in the path.
    internal func with<T>(pushedKey key: CodingKey, _ work: () throws -> T) rethrows -> T {
        self.codingPath.append(key)
        let ret: T = try work()
        self.codingPath.removeLast()
        return ret
    }

    // MARK: - Decoder Methods

    public func container<Key>(keyedBy type: Key.Type) throws -> KeyedDecodingContainer<Key> {
        guard !(self.storage.topContainer is NSNull) else {
            throw DecodingError.valueNotFound(KeyedDecodingContainer<Key>.self,
                                              DecodingError.Context(codingPath: self.codingPath,
                                                                    debugDescription: "Cannot get keyed decoding container -- found null value instead."))
        }

        guard let topContainer = self.storage.topContainer as? [String : Any] else {
            throw DecodingError._typeMismatch(at: self.codingPath, expectation: [String : Any].self, reality: self.storage.topContainer)
        }

        let container = _XMLKeyedDecodingContainer<Key>(referencing: self, wrapping: topContainer)
        return KeyedDecodingContainer(container)
    }

    public func unkeyedContainer() throws -> UnkeyedDecodingContainer {
        guard !(self.storage.topContainer is NSNull) else {
            throw DecodingError.valueNotFound(UnkeyedDecodingContainer.self,
                                              DecodingError.Context(codingPath: self.codingPath,
                                                                    debugDescription: "Cannot get unkeyed decoding container -- found null value instead."))
        }

        guard let topContainer = self.storage.topContainer as? [Any] else {
            throw DecodingError._typeMismatch(at: self.codingPath, expectation: [Any].self, reality: self.storage.topContainer)
        }

        return _XMLUnkeyedDecodingContainer(referencing: self, wrapping: topContainer)
    }

    public func singleValueContainer() throws -> SingleValueDecodingContainer {
        return self
    }
}

// MARK: - Decoding Storage

internal struct _XMLDecodingStorage {
    // MARK: Properties

    /// The container stack.
    /// Elements may be any one of the XML types (NSNull, NSNumber, String, Array, [String : Any]).
    private(set) internal var containers: [Any] = []

    // MARK: - Initialization

    /// Initializes `self` with no containers.
    internal init() {}

    // MARK: - Modifying the Stack

    internal var count: Int {
        return self.containers.count
    }

    internal var topContainer: Any {
        precondition(self.containers.count > 0, "Empty container stack.")
        return self.containers.last!
    }

    internal mutating func push(container: Any) {
        self.containers.append(container)
    }

    internal mutating func popContainer() {
        precondition(self.containers.count > 0, "Empty container stack.")
        self.containers.removeLast()
    }
}

extension _XMLDecoder : SingleValueDecodingContainer {
    // MARK: SingleValueDecodingContainer Methods

    private func expectNonNull<T>(_ type: T.Type) throws {
        guard !self.decodeNil() else {
            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.codingPath, debugDescription: "Expected \(type) but found null value instead."))
        }
    }

    public func decodeNil() -> Bool {
        return self.storage.topContainer is NSNull
    }

    public func decode(_ type: Bool.Type) throws -> Bool {
        try expectNonNull(Bool.self)
        return try self.unbox(self.storage.topContainer, as: Bool.self)!
    }

    public func decode(_ type: Int.Type) throws -> Int {
        try expectNonNull(Int.self)
        return try self.unbox(self.storage.topContainer, as: Int.self)!
    }

    public func decode(_ type: Int8.Type) throws -> Int8 {
        try expectNonNull(Int8.self)
        return try self.unbox(self.storage.topContainer, as: Int8.self)!
    }

    public func decode(_ type: Int16.Type) throws -> Int16 {
        try expectNonNull(Int16.self)
        return try self.unbox(self.storage.topContainer, as: Int16.self)!
    }

    public func decode(_ type: Int32.Type) throws -> Int32 {
        try expectNonNull(Int32.self)
        return try self.unbox(self.storage.topContainer, as: Int32.self)!
    }

    public func decode(_ type: Int64.Type) throws -> Int64 {
        try expectNonNull(Int64.self)
        return try self.unbox(self.storage.topContainer, as: Int64.self)!
    }

    public func decode(_ type: UInt.Type) throws -> UInt {
        try expectNonNull(UInt.self)
        return try self.unbox(self.storage.topContainer, as: UInt.self)!
    }

    public func decode(_ type: UInt8.Type) throws -> UInt8 {
        try expectNonNull(UInt8.self)
        return try self.unbox(self.storage.topContainer, as: UInt8.self)!
    }

    public func decode(_ type: UInt16.Type) throws -> UInt16 {
        try expectNonNull(UInt16.self)
        return try self.unbox(self.storage.topContainer, as: UInt16.self)!
    }

    public func decode(_ type: UInt32.Type) throws -> UInt32 {
        try expectNonNull(UInt32.self)
        return try self.unbox(self.storage.topContainer, as: UInt32.self)!
    }

    public func decode(_ type: UInt64.Type) throws -> UInt64 {
        try expectNonNull(UInt64.self)
        return try self.unbox(self.storage.topContainer, as: UInt64.self)!
    }

    public func decode(_ type: Float.Type) throws -> Float {
        try expectNonNull(Float.self)
        return try self.unbox(self.storage.topContainer, as: Float.self)!
    }

    public func decode(_ type: Double.Type) throws -> Double {
        try expectNonNull(Double.self)
        return try self.unbox(self.storage.topContainer, as: Double.self)!
    }

    public func decode(_ type: String.Type) throws -> String {
        //print("---> SingleValueDecodingContainer.decode<String> type:", type)
        try expectNonNull(String.self)
        return try self.unbox(self.storage.topContainer, as: String.self)!
    }

    public func decode<T : Decodable>(_ type: T.Type) throws -> T {
        //print("---> SingleValueDecodingContainer.decode<T> type:", type)
        try expectNonNull(T.self)
        return try self.unbox(self.storage.topContainer, as: T.self)!
    }
}


//
//  _XMLDecoder_unbox.swift
//  azureSwiftRuntime
//
//  Created by Vladimir Shcherbakov on 1/17/18.
//

import Foundation

extension _XMLDecoder {
    /// Returns the given value unboxed from a container.
    internal func unbox(_ value: Any, as type: Bool.Type) throws -> Bool? {
        guard !(value is NSNull) else { return nil }

        guard let number = Bool(value as! String) else {
            throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
        }

        return number
    }

    internal func unbox(_ value: Any, as type: Int.Type) throws -> Int? {
        guard !(value is NSNull) else { return nil }

        guard let number = Int(value as! String) else {
            throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
        }

        return number
    }

    internal func unbox(_ value: Any, as type: Int8.Type) throws -> Int8? {
        guard !(value is NSNull) else { return nil }

        guard let number = Int8(value as! String) else {
            throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
        }

        return number
    }

    internal func unbox(_ value: Any, as type: Int16.Type) throws -> Int16? {
        guard !(value is NSNull) else { return nil }

        guard let number = Int16(value as! String) else {
            throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
        }

        return number
    }

    internal func unbox(_ value: Any, as type: Int32.Type) throws -> Int32? {
        guard !(value is NSNull) else { return nil }

        guard let number = Int32(value as! String) else {
            throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
        }

        return number
    }

    internal func unbox(_ value: Any, as type: Int64.Type) throws -> Int64? {
        guard !(value is NSNull) else { return nil }

        guard let number = Int64(value as! String) else {
            throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
        }

        return number
    }

    internal func unbox(_ value: Any, as type: UInt.Type) throws -> UInt? {
        guard !(value is NSNull) else { return nil }

        guard let number = UInt(value as! String) else {
            throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
        }

        return number
    }

    internal func unbox(_ value: Any, as type: UInt8.Type) throws -> UInt8? {
        guard !(value is NSNull) else { return nil }

        guard let number = UInt8(value as! String) else {
            throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
        }

        return number
    }

    internal func unbox(_ value: Any, as type: UInt16.Type) throws -> UInt16? {
        guard !(value is NSNull) else { return nil }

        guard let number = UInt16(value as! String) else {
            throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
        }

        return number
    }

    internal func unbox(_ value: Any, as type: UInt32.Type) throws -> UInt32? {
        guard !(value is NSNull) else { return nil }

        guard let number = UInt32(value as! String) else {
            throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
        }

        return number
    }

    internal func unbox(_ value: Any, as type: UInt64.Type) throws -> UInt64? {
        guard !(value is NSNull) else { return nil }

        guard let number = UInt64(value as! String) else {
            throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
        }

        return number
    }

    internal func unbox(_ value: Any, as type: Float.Type) throws -> Float? {
        guard !(value is NSNull) else { return nil }

        if let double = Double(value as! String) {
            // We are willing to return a Float by losing precision:
            // * If the original value was integral,
            //   * and the integral value was > Float.greatestFiniteMagnitude, we will fail
            //   * and the integral value was <= Float.greatestFiniteMagnitude, we are willing to lose precision past 2^24
            // * If it was a Float, you will get back the precise value
            // * If it was a Double or Decimal, you will get back the nearest approximation if it will fit
            //let double = number.doubleValue
            guard abs(double) <= Double(Float.greatestFiniteMagnitude) else {
                throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "Parsed XML number \(value) does not fit in \(type)."))
            }

            return Float(double)

            //return number

            /* FIXME: If swift-corelibs-foundation doesn't change to use NSNumber, this code path will need to be included and tested:
             } else if let double = value as? Double {
             if abs(double) <= Double(Float.max) {
             return Float(double)
             }

             overflow = true
             } else if let int = value as? Int {
             if let float = Float(exactly: int) {
             return float
             }

             overflow = true
             */

        } else if let string = value as? String,
            case .convertFromString(let posInfString, let negInfString, let nanString) = self.options.nonConformingFloatDecodingStrategy {
            if string == posInfString {
                return Float.infinity
            } else if string == negInfString {
                return -Float.infinity
            } else if string == nanString {
                return Float.nan
            }
        }

        throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
    }

    internal func unbox(_ value: Any, as type: Double.Type) throws -> Double? {
        guard !(value is NSNull) else { return nil }

        if let double = Double(value as! String) {
            // We are always willing to return the number as a Double:
            // * If the original value was integral, it is guaranteed to fit in a Double; we are willing to lose precision past 2^53 if you encoded a UInt64 but requested a Double
            // * If it was a Float or Double, you will get back the precise value
            // * If it was Decimal, you will get back the nearest approximation
            //return number.doubleValue
            return double

            /* FIXME: If swift-corelibs-foundation doesn't change to use NSNumber, this code path will need to be included and tested:
             } else if let double = value as? Double {
             return double
             } else if let int = value as? Int {
             if let double = Double(exactly: int) {
             return double
             }

             overflow = true
             */

        } else if let string = value as? String,
            case .convertFromString(let posInfString, let negInfString, let nanString) = self.options.nonConformingFloatDecodingStrategy {
            if string == posInfString {
                return Double.infinity
            } else if string == negInfString {
                return -Double.infinity
            } else if string == nanString {
                return Double.nan
            }
        }

        throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
    }

    internal func unbox(_ value: Any, as type: String.Type) throws -> String? {
        //print("---> unbox value:", value, "as:", type)
        guard !(value is NSNull) else { return nil }

        guard let string = value as? String else {
            throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
        }

        return string
    }

    internal func unbox(_ value: Any, as type: Date.Type) throws -> Date? {
        guard !(value is NSNull) else { return nil }

        switch self.options.dateDecodingStrategy {
        case .deferredToDate:
            self.storage.push(container: value)
            let date = try Date(from: self)
            self.storage.popContainer()
            return date

        case .secondsSince1970:
            let double = try self.unbox(value, as: Double.self)!
            return Date(timeIntervalSince1970: double)

        case .millisecondsSince1970:
            let double = try self.unbox(value, as: Double.self)!
            return Date(timeIntervalSince1970: double / 1000.0)

        case .iso8601:
            if #available(OSX 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *) {
                let string = try self.unbox(value, as: String.self)!
                guard let date = _iso8601Formatter.date(from: string) else {
                    throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "Expected date string to be ISO8601-formatted."))
                }

                return date
            } else {
                fatalError("ISO8601DateFormatter is unavailable on this platform.")
            }

        case .formatted(let formatter):
            let string = try self.unbox(value, as: String.self)!
            guard let date = formatter.date(from: string) else {
                throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "Date string does not match format expected by formatter."))
            }

            return date

        case .custom(let closure):
            self.storage.push(container: value)
            let date = try closure(self)
            self.storage.popContainer()
            return date
        }
    }

    internal func unbox(_ value: Any, as type: Data.Type) throws -> Data? {
        guard !(value is NSNull) else { return nil }

        switch self.options.dataDecodingStrategy {
        case .deferredToData:
            self.storage.push(container: value)
            let data = try Data(from: self)
            self.storage.popContainer()
            return data

        case .base64:
            guard let string = value as? String else {
                throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
            }

            guard let data = Data(base64Encoded: string) else {
                throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "Encountered Data is not valid Base64."))
            }

            return data

        case .custom(let closure):
            self.storage.push(container: value)
            let data = try closure(self)
            self.storage.popContainer()
            return data
        }
    }

    internal func unbox(_ value: Any, as type: Decimal.Type) throws -> Decimal? {
        guard !(value is NSNull) else { return nil }

        // On Darwin we get (value as? Decimal) since XMLSerialization can produce NSDecimalNumber values.
        // FIXME: Attempt to grab a Decimal value if XMLSerialization on Linux produces one.
        let doubleValue = try self.unbox(value, as: Double.self)!
        return Decimal(doubleValue)
    }

    internal func unbox<T : Decodable>(_ value: Any, as type: T.Type) throws -> T? {
        //print("---> unbox <T> value:", value, "as:", type)
        let decoded: T
        if T.self == Date.self {
            guard let date = try self.unbox(value, as: Date.self) else { return nil }
            decoded = date as! T
        } else if T.self == Data.self {
            guard let data = try self.unbox(value, as: Data.self) else { return nil }
            decoded = data as! T
        } else if T.self == URL.self {
            guard let urlString = try self.unbox(value, as: String.self) else {
                return nil
            }

            guard let url = URL(string: urlString) else {
                throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath,
                                                                        debugDescription: "Invalid URL string."))
            }

            decoded = (url as! T)
        } else if T.self == Decimal.self {
            guard let decimal = try self.unbox(value, as: Decimal.self) else { return nil }
            decoded = decimal as! T
        } else {
            self.storage.push(container: value)
            decoded = try T(from: self)
            self.storage.popContainer()
        }

        return decoded
    }
}


//
//  _XMLKeyedDecodingContainer.swift
//  azureSwiftRuntime
//
//  Created by Vladimir Shcherbakov on 1/17/18.
//

import Foundation

internal struct _XMLKeyedDecodingContainer<K : CodingKey> : KeyedDecodingContainerProtocol {
    typealias Key = K

    // MARK: Properties

    /// A reference to the decoder we're reading from.
    private let decoder: _XMLDecoder

    /// A reference to the container we're reading from.
    private let container: [String : Any]

    /// The path of coding keys taken to get to this point in decoding.
    private(set) public var codingPath: [CodingKey]

    // MARK: - Initialization

    /// Initializes `self` by referencing the given decoder and container.
    internal init(referencing decoder: _XMLDecoder, wrapping container: [String : Any]) {
        self.decoder = decoder
        self.container = container
        self.codingPath = decoder.codingPath
    }

    // MARK: - KeyedDecodingContainerProtocol Methods

    public var allKeys: [Key] {
        return self.container.keys.map { Key(stringValue: $0)! }
    }

    public func contains(_ key: Key) -> Bool {
        return self.container[key.stringValue] != nil
    }

    public func decodeNil(forKey key: Key) throws -> Bool {
        guard let entry = self.container[key.stringValue] else {
            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
        }

        return entry is NSNull
    }

    public func decode(_ type: Bool.Type, forKey key: Key) throws -> Bool {
        guard let entry = self.container[key.stringValue] else {
            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
        }

        return try self.decoder.with(pushedKey: key) {
            guard let value = try self.decoder.unbox(entry, as: Bool.self) else {
                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
            }

            return value
        }
    }

    public func decode(_ type: Int.Type, forKey key: Key) throws -> Int {
        guard let entry = self.container[key.stringValue] else {
            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
        }

        return try self.decoder.with(pushedKey: key) {
            guard let value = try self.decoder.unbox(entry, as: Int.self) else {
                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
            }

            return value
        }
    }

    public func decode(_ type: Int?.Type, forKey key: Key) throws -> Int? {
        guard let entry = self.container[key.stringValue] else {
            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
        }

        return try self.decoder.with(pushedKey: key) {
            guard let value = try self.decoder.unbox(entry, as: Int.self) else {
                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
            }

            return value
        }
    }

    public func decode(_ type: Int8.Type, forKey key: Key) throws -> Int8 {
        guard let entry = self.container[key.stringValue] else {
            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
        }

        return try self.decoder.with(pushedKey: key) {
            guard let value = try self.decoder.unbox(entry, as: Int8.self) else {
                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
            }

            return value
        }
    }

    public func decode(_ type: Int16.Type, forKey key: Key) throws -> Int16 {
        guard let entry = self.container[key.stringValue] else {
            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
        }

        return try self.decoder.with(pushedKey: key) {
            guard let value = try self.decoder.unbox(entry, as: Int16.self) else {
                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
            }

            return value
        }
    }

    public func decode(_ type: Int32.Type, forKey key: Key) throws -> Int32 {
        guard let entry = self.container[key.stringValue] else {
            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
        }

        return try self.decoder.with(pushedKey: key) {
            guard let value = try self.decoder.unbox(entry, as: Int32.self) else {
                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
            }

            return value
        }
    }

    public func decode(_ type: Int64.Type, forKey key: Key) throws -> Int64 {
        guard let entry = self.container[key.stringValue] else {
            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
        }

        return try self.decoder.with(pushedKey: key) {
            guard let value = try self.decoder.unbox(entry, as: Int64.self) else {
                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
            }

            return value
        }
    }

    public func decode(_ type: UInt.Type, forKey key: Key) throws -> UInt {
        guard let entry = self.container[key.stringValue] else {
            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
        }

        return try self.decoder.with(pushedKey: key) {
            guard let value = try self.decoder.unbox(entry, as: UInt.self) else {
                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
            }

            return value
        }
    }

    public func decode(_ type: UInt8.Type, forKey key: Key) throws -> UInt8 {
        guard let entry = self.container[key.stringValue] else {
            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
        }

        return try self.decoder.with(pushedKey: key) {
            guard let value = try self.decoder.unbox(entry, as: UInt8.self) else {
                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
            }

            return value
        }
    }

    public func decode(_ type: UInt16.Type, forKey key: Key) throws -> UInt16 {
        guard let entry = self.container[key.stringValue] else {
            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
        }

        return try self.decoder.with(pushedKey: key) {
            guard let value = try self.decoder.unbox(entry, as: UInt16.self) else {
                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
            }

            return value
        }
    }

    public func decode(_ type: UInt32.Type, forKey key: Key) throws -> UInt32 {
        guard let entry = self.container[key.stringValue] else {
            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
        }

        return try self.decoder.with(pushedKey: key) {
            guard let value = try self.decoder.unbox(entry, as: UInt32.self) else {
                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
            }

            return value
        }
    }

    public func decode(_ type: UInt64.Type, forKey key: Key) throws -> UInt64 {
        guard let entry = self.container[key.stringValue] else {
            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
        }

        return try self.decoder.with(pushedKey: key) {
            guard let value = try self.decoder.unbox(entry, as: UInt64.self) else {
                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
            }

            return value
        }
    }

    public func decode(_ type: Float.Type, forKey key: Key) throws -> Float {
        guard let entry = self.container[key.stringValue] else {
            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
        }

        return try self.decoder.with(pushedKey: key) {
            guard let value = try self.decoder.unbox(entry, as: Float.self) else {
                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
            }

            return value
        }
    }

    public func decode(_ type: Double.Type, forKey key: Key) throws -> Double {
        guard let entry = self.container[key.stringValue] else {
            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
        }

        return try self.decoder.with(pushedKey: key) {
            guard let value = try self.decoder.unbox(entry, as: Double.self) else {
                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
            }

            return value
        }
    }

    public func decode(_ type: String.Type, forKey key: Key) throws -> String {
        //print("---> KeyedDecodingContainer.decode<String> type:", type)
        guard let entry = self.container[key.stringValue] else {
            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
        }

        //print("\tentry:", entry)

        return try self.decoder.with(pushedKey: key) {
            guard let value = try self.decoder.unbox(entry, as: String.self) else {
                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
            }

            return value
        }
    }

    public func decode<T : Decodable>(_ type: T.Type, forKey key: Key) throws -> T {
        //print("---> KeyedDecodingContainer.decode<T> type:", type)
        guard var entry = self.container[key.stringValue] else {
            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
        }
        /*
         FIXME: in XML in case of a single entry it's hard to predict if it's an array or map
         if number of entries is more then one - an array differs from a map by the key repetition:

         XML map example:
         <collection>
            <string1>Hello</string1>
            <string2>World</string2>
         </collection>

         XML array example:
         <collection>
            <string>Hello</string>
            <string>World</string>
         </collection>

         So, in case of a single entry collection if an expected type is Array by actual type is Map -
         convert the map into array by using the map value as a single entry array.
        */

        if let map = entry as? [String:Any] {
            if map.count == 1
                && ("\(T.self)".starts(with: "Array")
                    || "\(T.self)".starts(with: "Optional<Array")) {
                let (_,val) = map.first!
                entry = [val]
            }
        }

        return try self.decoder.with(pushedKey: key) {
            guard let value = try self.decoder.unbox(entry, as: T.self) else {
                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
            }

            return value
        }
    }

    public func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type, forKey key: Key) throws -> KeyedDecodingContainer<NestedKey> {
        return try self.decoder.with(pushedKey: key) {
            guard let value = self.container[key.stringValue] else {
                throw DecodingError.keyNotFound(key,
                                                DecodingError.Context(codingPath: self.codingPath,
                                                                      debugDescription: "Cannot get \(KeyedDecodingContainer<NestedKey>.self) -- no value found for key \"\(key.stringValue)\""))
            }

            guard let dictionary = value as? [String : Any] else {
                throw DecodingError._typeMismatch(at: self.codingPath, expectation: [String : Any].self, reality: value)
            }

            let container = _XMLKeyedDecodingContainer<NestedKey>(referencing: self.decoder, wrapping: dictionary)
            return KeyedDecodingContainer(container)
        }
    }

    public func nestedUnkeyedContainer(forKey key: Key) throws -> UnkeyedDecodingContainer {
        return try self.decoder.with(pushedKey: key) {
            guard let value = self.container[key.stringValue] else {
                throw DecodingError.keyNotFound(key,
                                                DecodingError.Context(codingPath: self.codingPath,
                                                                      debugDescription: "Cannot get UnkeyedDecodingContainer -- no value found for key \"\(key.stringValue)\""))
            }

            guard let array = value as? [Any] else {
                throw DecodingError._typeMismatch(at: self.codingPath, expectation: [Any].self, reality: value)
            }

            return _XMLUnkeyedDecodingContainer(referencing: self.decoder, wrapping: array)
        }
    }

    private func _superDecoder(forKey key: CodingKey) throws -> Decoder {
        return self.decoder.with(pushedKey: key) {
            let value: Any = self.container[key.stringValue] ?? NSNull()
            return _XMLDecoder(referencing: value, at: self.decoder.codingPath, options: self.decoder.options)
        }
    }

    public func superDecoder() throws -> Decoder {
        return try _superDecoder(forKey: _XMLKey.super)
    }

    public func superDecoder(forKey key: Key) throws -> Decoder {
        return try _superDecoder(forKey: key)
    }
}


//
//  _XMLUnkeyedDecodingContainer.swift
//  azureSwiftRuntimePackageDescription
//
//  Created by Vladimir Shcherbakov on 1/19/18.
//

import Foundation

internal struct _XMLUnkeyedDecodingContainer : UnkeyedDecodingContainer {
    // MARK: Properties

    /// A reference to the decoder we're reading from.
    private let decoder: _XMLDecoder

    /// A reference to the container we're reading from.
    private let container: [Any]

    /// The path of coding keys taken to get to this point in decoding.
    private(set) public var codingPath: [CodingKey]

    /// The index of the element we're about to decode.
    private(set) public var currentIndex: Int

    // MARK: - Initialization

    /// Initializes `self` by referencing the given decoder and container.
    internal init(referencing decoder: _XMLDecoder, wrapping container: [Any]) {
        self.decoder = decoder
        self.container = container
        self.codingPath = decoder.codingPath
        self.currentIndex = 0
    }

    // MARK: - UnkeyedDecodingContainer Methods

    public var count: Int? {
        return self.container.count
    }

    public var isAtEnd: Bool {
        return self.currentIndex >= self.count!
    }

    public mutating func decodeNil() throws -> Bool {
        guard !self.isAtEnd else {
            throw DecodingError.valueNotFound(Any?.self, DecodingError.Context(codingPath: self.decoder.codingPath + [_XMLKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
        }

        if self.container[self.currentIndex] is NSNull {
            self.currentIndex += 1
            return true
        } else {
            return false
        }
    }

    public mutating func decode(_ type: Bool.Type) throws -> Bool {
        guard !self.isAtEnd else {
            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_XMLKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
        }

        return try self.decoder.with(pushedKey: _XMLKey(index: self.currentIndex)) {
            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Bool.self) else {
                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_XMLKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
            }

            self.currentIndex += 1
            return decoded
        }
    }

    public mutating func decode(_ type: Int.Type) throws -> Int {
        guard !self.isAtEnd else {
            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_XMLKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
        }

        return try self.decoder.with(pushedKey: _XMLKey(index: self.currentIndex)) {
            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int.self) else {
                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_XMLKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
            }

            self.currentIndex += 1
            return decoded
        }
    }

    public mutating func decode(_ type: Int8.Type) throws -> Int8 {
        guard !self.isAtEnd else {
            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_XMLKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
        }

        return try self.decoder.with(pushedKey: _XMLKey(index: self.currentIndex)) {
            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int8.self) else {
                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_XMLKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
            }

            self.currentIndex += 1
            return decoded
        }
    }

    public mutating func decode(_ type: Int16.Type) throws -> Int16 {
        guard !self.isAtEnd else {
            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_XMLKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
        }

        return try self.decoder.with(pushedKey: _XMLKey(index: self.currentIndex)) {
            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int16.self) else {
                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_XMLKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
            }

            self.currentIndex += 1
            return decoded
        }
    }

    public mutating func decode(_ type: Int32.Type) throws -> Int32 {
        guard !self.isAtEnd else {
            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_XMLKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
        }

        return try self.decoder.with(pushedKey: _XMLKey(index: self.currentIndex)) {
            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int32.self) else {
                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_XMLKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
            }

            self.currentIndex += 1
            return decoded
        }
    }

    public mutating func decode(_ type: Int64.Type) throws -> Int64 {
        guard !self.isAtEnd else {
            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_XMLKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
        }

        return try self.decoder.with(pushedKey: _XMLKey(index: self.currentIndex)) {
            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int64.self) else {
                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_XMLKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
            }

            self.currentIndex += 1
            return decoded
        }
    }

    public mutating func decode(_ type: UInt.Type) throws -> UInt {
        guard !self.isAtEnd else {
            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_XMLKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
        }

        return try self.decoder.with(pushedKey: _XMLKey(index: self.currentIndex)) {
            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt.self) else {
                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_XMLKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
            }

            self.currentIndex += 1
            return decoded
        }
    }

    public mutating func decode(_ type: UInt8.Type) throws -> UInt8 {
        guard !self.isAtEnd else {
            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_XMLKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
        }

        return try self.decoder.with(pushedKey: _XMLKey(index: self.currentIndex)) {
            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt8.self) else {
                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_XMLKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
            }

            self.currentIndex += 1
            return decoded
        }
    }

    public mutating func decode(_ type: UInt16.Type) throws -> UInt16 {
        guard !self.isAtEnd else {
            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_XMLKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
        }

        return try self.decoder.with(pushedKey: _XMLKey(index: self.currentIndex)) {
            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt16.self) else {
                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_XMLKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
            }

            self.currentIndex += 1
            return decoded
        }
    }

    public mutating func decode(_ type: UInt32.Type) throws -> UInt32 {
        guard !self.isAtEnd else {
            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_XMLKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
        }

        return try self.decoder.with(pushedKey: _XMLKey(index: self.currentIndex)) {
            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt32.self) else {
                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_XMLKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
            }

            self.currentIndex += 1
            return decoded
        }
    }

    public mutating func decode(_ type: UInt64.Type) throws -> UInt64 {
        guard !self.isAtEnd else {
            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_XMLKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
        }

        return try self.decoder.with(pushedKey: _XMLKey(index: self.currentIndex)) {
            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt64.self) else {
                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_XMLKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
            }

            self.currentIndex += 1
            return decoded
        }
    }

    public mutating func decode(_ type: Float.Type) throws -> Float {
        guard !self.isAtEnd else {
            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_XMLKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
        }

        return try self.decoder.with(pushedKey: _XMLKey(index: self.currentIndex)) {
            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Float.self) else {
                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_XMLKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
            }

            self.currentIndex += 1
            return decoded
        }
    }

    public mutating func decode(_ type: Double.Type) throws -> Double {
        guard !self.isAtEnd else {
            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_XMLKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
        }

        return try self.decoder.with(pushedKey: _XMLKey(index: self.currentIndex)) {
            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Double.self) else {
                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_XMLKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
            }

            self.currentIndex += 1
            return decoded
        }
    }

    public mutating func decode(_ type: String.Type) throws -> String {
        //print("---> UnkeyedDecodingContainer.decode<String> type:", type)
        guard !self.isAtEnd else {
            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_XMLKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
        }

        return try self.decoder.with(pushedKey: _XMLKey(index: self.currentIndex)) {
            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: String.self) else {
                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_XMLKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
            }

            self.currentIndex += 1
            return decoded
        }
    }

    public mutating func decode<T : Decodable>(_ type: T.Type) throws -> T {
        //print("---> UnkeyedDecodingContainer.decode<T> type:", type)
        guard !self.isAtEnd else {
            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_XMLKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
        }

        return try self.decoder.with(pushedKey: _XMLKey(index: self.currentIndex)) {
            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: T.self) else {
                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_XMLKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
            }

            self.currentIndex += 1
            return decoded
        }
    }

    public mutating func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type) throws -> KeyedDecodingContainer<NestedKey> {
        return try self.decoder.with(pushedKey: _XMLKey(index: self.currentIndex)) {
            guard !self.isAtEnd else {
                throw DecodingError.valueNotFound(KeyedDecodingContainer<NestedKey>.self,
                                                  DecodingError.Context(codingPath: self.codingPath,
                                                                        debugDescription: "Cannot get nested keyed container -- unkeyed container is at end."))
            }

            let value = self.container[self.currentIndex]
            guard !(value is NSNull) else {
                throw DecodingError.valueNotFound(KeyedDecodingContainer<NestedKey>.self,
                                                  DecodingError.Context(codingPath: self.codingPath,
                                                                        debugDescription: "Cannot get keyed decoding container -- found null value instead."))
            }

            guard let dictionary = value as? [String : Any] else {
                throw DecodingError._typeMismatch(at: self.codingPath, expectation: [String : Any].self, reality: value)
            }

            self.currentIndex += 1
            let container = _XMLKeyedDecodingContainer<NestedKey>(referencing: self.decoder, wrapping: dictionary)
            return KeyedDecodingContainer(container)
        }
    }

    public mutating func nestedUnkeyedContainer() throws -> UnkeyedDecodingContainer {
        return try self.decoder.with(pushedKey: _XMLKey(index: self.currentIndex)) {
            guard !self.isAtEnd else {
                throw DecodingError.valueNotFound(UnkeyedDecodingContainer.self,
                                                  DecodingError.Context(codingPath: self.codingPath,
                                                                        debugDescription: "Cannot get nested keyed container -- unkeyed container is at end."))
            }

            let value = self.container[self.currentIndex]
            guard !(value is NSNull) else {
                throw DecodingError.valueNotFound(UnkeyedDecodingContainer.self,
                                                  DecodingError.Context(codingPath: self.codingPath,
                                                                        debugDescription: "Cannot get keyed decoding container -- found null value instead."))
            }

            guard let array = value as? [Any] else {
                throw DecodingError._typeMismatch(at: self.codingPath, expectation: [Any].self, reality: value)
            }

            self.currentIndex += 1
            return _XMLUnkeyedDecodingContainer(referencing: self.decoder, wrapping: array)
        }
    }

    public mutating func superDecoder() throws -> Decoder {
        return try self.decoder.with(pushedKey: _XMLKey(index: self.currentIndex)) {
            guard !self.isAtEnd else {
                throw DecodingError.valueNotFound(Decoder.self,
                                                  DecodingError.Context(codingPath: self.codingPath,
                                                                        debugDescription: "Cannot get superDecoder() -- unkeyed container is at end."))
            }

            let value = self.container[self.currentIndex]
            self.currentIndex += 1
            return _XMLDecoder(referencing: value, at: self.decoder.codingPath, options: self.decoder.options)
        }
    }
}


/**
 * Copyright (c) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License. See License.txt in the project root for
 * license information.
 */

import XCTest
import RxSwift
@testable import azureSwiftRuntime

class AuthTests: XCTestCase {

    let envVarName = "AUTH_FILE_PATH"
    var filepath = String()
    let timeout: TimeInterval = 100.0

    var applicationTokenCredentials: ApplicationTokenCredentials!
    var azureClient: AzureClient!

    override func setUp() {
        continueAfterFailure = false
        super.setUp()
        guard let filepath = self.getEnvironmentVar(name: envVarName.uppercased()) else {
            XCTFail("Azure auth file path is not set in env var \(envVarName))")
            return
        }
        self.filepath = filepath

        self.applicationTokenCredentials = try? ApplicationTokenCredentials.fromFile(path: filepath)
        let headersToHide = ["Authorization"]
        self.azureClient = AzureClient(atc: applicationTokenCredentials)
            .withRequestInterceptor(LogRequestInterceptor(showOptions: .all).withHeadersToHide(headersToHide))
            .withResponseInterceptor(LogResponseInterceptor(showOptions: .all))
    }

    func testAuthFile() {
        XCTAssertNoThrow(try AuthFile.parseJsonFile(path: filepath))
    }

    func testApplicationTokenCredentials() {
        let e = expectation(description: "Wait for HTTP request to compleate")
        do {
            let atc = try ApplicationTokenCredentials.fromFile(path: filepath)
            _ = try atc.authHeaderValue(url: nil)
            e.fulfill()
        } catch {
            print("=== Error:", error)
            XCTFail()
        }

        waitForExpectations(timeout: timeout, handler: nil)
    }

    class AzureAuthCommand : BaseCommand {

        override init() {
            super.init()
            self.method = "Get"
            self.isLongRunningOperation = false
            self.path = "/subscriptions?api-version=2016-06-01"
        }

        override func returnFunc(data: Data) throws -> Decodable? {
            return try CoderFactory.decoder(for: .json).decode(Subscription?.self, from: data)
        }

        public func executeAsync(client: RuntimeClient, completionHandler: @escaping (Subscription?, Error?) -> Void) {
            client.executeAsync(command: self) {
                (result, error)  in
                completionHandler(result, error)
            }
        }

        public func executeAsync(client: RuntimeClient) -> Observable<Subscription?> {
            return client.executeAsync(command: self)
        }

        struct Subscription : Codable {
            let value: [SubscriptionData]
        }

        struct SubscriptionData : Codable {
            let id: String
            let subscriptionId: String
            let displayName: String
            let state: String
            let subscriptionPolicies: SubscriptionPolicies
            let authorizationSource: String?

            struct SubscriptionPolicies : Codable {
                let locationPlacementId: String
                let quotaId: String
                let spendingLimit: String
            }
        }
    }

    func testAzureAuth() {
        print("\n=================== #1 AzureAuth()\n")
        let e = expectation(description: "Wait for HTTP request to compleate")

        let cmd = AzureAuthCommand()
        cmd.executeAsync(client: self.azureClient) {
            result, error in
            defer { e.fulfill() }

            do {
                if let curError = error {
                    throw curError
                }

                XCTAssertNotNil(result)
                if let subscriptions = result?.value {
                    if subscriptions.count > 0 {
                        print("Subscriptions ===")
                        for sub in subscriptions {
                            print("\tname: \(sub.displayName), id: \(sub.subscriptionId)")
                        }
                    }
                }
            } catch {
                print("=== Error:", error)
                XCTFail(error.localizedDescription)
            }
        }

        waitForExpectations(timeout: timeout, handler: nil)
    }

    func testAzureAuthObservable() {
        print("\n=================== #2 AzureAuthObservable\n")
        let e = expectation(description: "Wait for HTTP request to compleate")
        let disposeBag = DisposeBag()
        let cmd = AzureAuthCommand()
        cmd.executeAsync(client: self.azureClient).subscribe(
            onNext: { result in
                defer { e.fulfill() }
                XCTAssertNotNil(result)
                if let subscriptions = result?.value {
                    XCTAssertTrue(subscriptions.count > 0)
                    if subscriptions.count > 0 {
                        print("Subscriptions ===")
                        for sub in subscriptions {
                            print("\tname: \(sub.displayName), id: \(sub.subscriptionId)")
                        }
                    }
                } else {
                    XCTFail("subscriptions in nil")
                }
            },
            onError: { error in
                defer { e.fulfill() }
                XCTFail(error.localizedDescription)
            }
        ).disposed(by: disposeBag)

        waitForExpectations(timeout: timeout, handler: nil)
    }

    // === private helpers

    func getEnvironmentVar(name: String) -> String? {
        guard let rawValue = getenv(name) else { return nil }
        return String(utf8String: rawValue)
    }

}


/**
 * Copyright (c) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License. See License.txt in the project root for
 * license information.
 */

import Foundation
import XCTest
import azureSwiftRuntime

class BodyBooleanQuirksTests: XCTestCase {

    let timeout: TimeInterval = 102.0
    var azureClient: AzureClient!

    override func setUp() {
        continueAfterFailure = false

        let env = AuzureEnvironment(endpoints:[
            .resourceManager : "http://localhost:3000"
            ])

        let atc = AzureTokenCredentials(environment: env, tenantId: "", subscriptionId: "")

        self.azureClient = AzureClient(atc: atc)
            .withRequestInterceptor(LogRequestInterceptor(showOptions: .all))
            .withResponseInterceptor(LogResponseInterceptor(showOptions: .all))

        super.setUp()
    }

    override func tearDown() {
        // Put teardown code here. This method is called after the invocation of each test method in the class.
        super.tearDown()
    }

    func test_bool_putTrue() {
        print("\n=================== #1.1 bool_getTrue\n")

        let cmd = BoolNamespace.PutTrueCommand()
        cmd.boolBody = true

        do {
            let res = try cmd.execute(client: self.azureClient)
            XCTAssertNil(res)
        } catch {
            XCTFail(error.localizedDescription)
            print("=== Error:", error)
        }
    }

    func test_bool_getTrue() {
        print("\n=================== #1.2 bool_putTrue\n")

        let cmd = BoolNamespace.GetTrueCommand()
        let expectedResult = true
        do {
            let res = try cmd.execute(client: self.azureClient)
            XCTAssertNotNil(res)
            XCTAssertEqual(expectedResult, res!)
        } catch {
            XCTFail(error.localizedDescription)
            print("=== Error:", error)
        }
    }

    func test_bool_putFalse() {
        print("\n=================== #2.1 bool_putFalse\n")

        let cmd = BoolNamespace.PutFalseCommand()
        cmd.boolBody = false

        do {
            let res = try cmd.execute(client: self.azureClient)
            XCTAssertNil(res)
        } catch {
            XCTFail(error.localizedDescription)
            print("=== Error:", error)
        }
    }

    func test_bool_getFalse() {
        print("\n=================== #2.2 bool_getFalse\n")

        let cmd = BoolNamespace.GetFalseCommand()
        let expectedResult = false

        do {
            let res = try cmd.execute(client: self.azureClient)
            XCTAssertNotNil(res)
            XCTAssertEqual(expectedResult, res!)
        } catch {
            XCTFail(error.localizedDescription)
            print("=== Error:", error)
        }
    }

    func test_bool_getNull() {
        print("\n=================== #3 bool_getNull\n")

        let cmd = BoolNamespace.GetNullCommand()

        do {
            let res = try cmd.execute(client: self.azureClient)
            XCTAssertNil(res)
        } catch {
            print("=== Error:", error)
            XCTFail(error.localizedDescription)
        }
    }

    func test_bool_getInvalid() {
        print("\n=================== #4 bool_getInvalid\n")

        let cmd = BoolNamespace.GetInvalidCommand()

        do {
            let res = try cmd.execute(client: self.azureClient)
            XCTAssertNil(res)
        } catch {
            print("=== Error:", error)
            if (error as NSError).code != 3840 {
                XCTFail(error.localizedDescription)
            }
        }
    }
}


//
//  BodyDate.swift
//  azureSwiftRuntimeTests
//
//  Created by Vladimir Shcherbakov on 12/27/17.
//

import Foundation
import XCTest
import azureSwiftRuntime

class BodyDateTests: XCTestCase {

    let timeout: TimeInterval = 102.0
    var azureClient: AzureClient!

    override func setUp() {
        continueAfterFailure = false

        let env = AuzureEnvironment(endpoints:[
            .resourceManager : "http://localhost:3000"
        ])

        let atc = AzureTokenCredentials(environment: env, tenantId: "", subscriptionId: "")

        self.azureClient = AzureClient(atc: atc)
            .withRequestInterceptor(LogRequestInterceptor(showOptions: .all))
            .withResponseInterceptor(LogResponseInterceptor(showOptions: .all))

        super.setUp()
    }

    override func tearDown() {
        // Put teardown code here. This method is called after the invocation of each test method in the class.
        super.tearDown()
    }

    func test_date_getNull() {
        print("\n=================== #1 date_getNull\n")

        let e = expectation(description: "Wait for HTTP request to complete")

        let cmd = DateNamespace.GetNullCommand()

        cmd.execute(client: self.azureClient) { (result, error) in
            defer { e.fulfill() }
            XCTAssertNil(error)
            XCTAssertNil(result)
        }

        waitForExpectations(timeout: timeout, handler: nil)
    }

    func test_date_getInvalidDate() {
        print("\n=================== #2 date_getInvalidDate\n")

        let e = expectation(description: "Wait for HTTP request to complete")

        let cmd = DateNamespace.GetInvalidDateCommand()

        cmd.execute(client: self.azureClient) { (result, error) in
            defer { e.fulfill() }
            XCTAssertNil(error)
            //"201O-18-90"
            XCTAssertNil(result)
        }

        waitForExpectations(timeout: timeout, handler: nil)
    }

    func test_date_getOverflowDate() {
        print("\n=================== #3 date_getOverflowDate\n")

        let e = expectation(description: "Wait for HTTP request to complete")

        let cmd = DateNamespace.GetOverflowDateCommand()

        cmd.execute(client: self.azureClient) { (result, error) in
            defer { e.fulfill() }
            XCTAssertNil(error)
            //"10000000000-12-31"
            XCTAssertNil(result)
        }

        waitForExpectations(timeout: timeout, handler: nil)
    }

    func test_date_getUnderflowDate() {
        print("\n=================== #4 date_getUnderflowDate\n")

        let e = expectation(description: "Wait for HTTP request to complete")

        let cmd = DateNamespace.GetUnderflowDateCommand()

        cmd.execute(client: self.azureClient) { (result, error) in
            defer { e.fulfill() }
            XCTAssertNil(error)
            //"0000-00-00"
            XCTAssertNil(result)
        }

        waitForExpectations(timeout: timeout, handler: nil)
    }

    func test_date_putMaxDate() {
        print("\n=================== #4 date_putMaxDate\n")

        let e = expectation(description: "Wait for HTTP request to complete")

        let cmd = DateNamespace.PutMaxDateCommand()
        cmd.dateBody = Date(fromString: "9999-12-31", format: .date)
        XCTAssertNotNil(cmd.dateBody)

        cmd.execute(client: self.azureClient) { (error) in
            defer { e.fulfill() }
            XCTAssertNil(error)
        }

        waitForExpectations(timeout: timeout, handler: nil)
    }

    func test_date_getMaxDate() {
        print("\n=================== #4 date_getMaxDate\n")

        let e = expectation(description: "Wait for HTTP request to complete")

        let cmd = DateNamespace.GetMaxDateCommand()

        cmd.execute(client: self.azureClient) { (result, error) in
            defer { e.fulfill() }
            XCTAssertNil(error)
            //"9999-12-31"
            XCTAssertNotNil(result)
            let date = result!
            XCTAssertNotNil(date)
            let calendar = Calendar.current
            let components = calendar.dateComponents(in: TimeZone(identifier: "GMT")!, from: date)
            XCTAssertEqual(9999, components.year)
            XCTAssertEqual(12, components.month)
            XCTAssertEqual(31, components.day)
        }

        waitForExpectations(timeout: timeout, handler: nil)
    }

    func test_date_putMinDate() {
        print("\n=================== #4 date_putMinDate\n")

        let e = expectation(description: "Wait for HTTP request to complete")

        let cmd = DateNamespace.PutMinDateCommand()
        cmd.dateBody = Date(fromString: "0001-01-01", format: .date)
        XCTAssertNotNil(cmd.dateBody)

        cmd.execute(client: self.azureClient) { (error) in
            defer { e.fulfill() }
            XCTAssertNil(error)
        }

        waitForExpectations(timeout: timeout, handler: nil)
    }

    func test_date_getMinDate() {
        print("\n=================== #4 date_getMinDate\n")

        let e = expectation(description: "Wait for HTTP request to complete")

        let cmd = DateNamespace.GetMinDateCommand()

        cmd.execute(client: self.azureClient) { (result, error) in
            defer { e.fulfill() }
            XCTAssertNil(error)
            XCTAssertNotNil(result)

            let date = result!
            XCTAssertNotNil(date)

            let calendar = Calendar.current
            let components = calendar.dateComponents(in: TimeZone(identifier: "GMT")!, from: date)
            XCTAssertEqual(1, components.year)
            XCTAssertEqual(1, components.month)
            XCTAssertEqual(1, components.day)
        }

        waitForExpectations(timeout: timeout, handler: nil)
    }
}