// Models.swift
//
// Generated by swagger-codegen
// https://github.com/swagger-api/swagger-codegen
//

import Foundation

protocol JSONEncodable {
    func encodeToJSON() -> AnyObject
}

public class Response<T> {
    public let statusCode: Int
    public let header: [String: String]
    public let body: T

    public init(statusCode: Int, header: [String: String], body: T) {
        self.statusCode = statusCode
        self.header = header
        self.body = body
    }

    public convenience init(response: NSHTTPURLResponse, body: T) {
        let rawHeader = response.allHeaderFields
        var header = [String:String]()
        for (key, value) in rawHeader {
            header[key as! String] = value as? String
        }
        self.init(statusCode: response.statusCode, header: header, body: body)
    }
}

private var once = dispatch_once_t()
class Decoders {
    static private var decoders = Dictionary<String, ((AnyObject) -> AnyObject)>()

    static func addDecoder<T>(clazz clazz: T.Type, decoder: ((AnyObject) -> T)) {
        let key = "\(T.self)"
        decoders[key] = { decoder($0) as! AnyObject }
    }

    static func decode<T>(clazz clazz: [T].Type, source: AnyObject) -> [T] {
        let array = source as! [AnyObject]
        return array.map { Decoders.decode(clazz: T.self, source: $0) }
    }

    static func decode<T, Key: Hashable>(clazz clazz: [Key:T].Type, source: AnyObject) -> [Key:T] {
        let sourceDictionary = source as! [Key: AnyObject]
        var dictionary = [Key:T]()
        for (key, value) in sourceDictionary {
            dictionary[key] = Decoders.decode(clazz: T.self, source: value)
        }
        return dictionary
    }

    static func decode<T>(clazz clazz: T.Type, source: AnyObject) -> T {
        initialize()
        if T.self is Int32.Type && source is NSNumber {
            return source.intValue as! T;
        }
        if T.self is Int64.Type && source is NSNumber {
            return source.longLongValue as! T;
        }
        if source is T {
            return source as! T
        }

        let key = "\(T.self)"
        if let decoder = decoders[key] {
           return decoder(source) as! T
        } else {
            fatalError("Source \(source) is not convertible to type \(clazz): Maybe swagger file is insufficient")
        }
    }

    static func decodeOptional<T>(clazz clazz: T.Type, source: AnyObject?) -> T? {
        if source is NSNull {
            return nil
        }
        return source.map { (source: AnyObject) -> T in
            Decoders.decode(clazz: clazz, source: source)
        }
    }

    static func decodeOptional<T>(clazz clazz: [T].Type, source: AnyObject?) -> [T]? {
        if source is NSNull {
            return nil
        }
        return source.map { (someSource: AnyObject) -> [T] in
            Decoders.decode(clazz: clazz, source: someSource)
        }
    }

    static func decodeOptional<T, Key: Hashable>(clazz clazz: [Key:T].Type, source: AnyObject?) -> [Key:T]? {
        if source is NSNull {
            return nil
        }
        return source.map { (someSource: AnyObject) -> [Key:T] in
            Decoders.decode(clazz: clazz, source: someSource)
        }
    }

    static private func initialize() {
        dispatch_once(&once) {
            let formatters = [
                "yyyy-MM-dd",
                "yyyy-MM-dd'T'HH:mm:ssZZZZZ",
                "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ",
                "yyyy-MM-dd'T'HH:mm:ss'Z'",
                "yyyy-MM-dd'T'HH:mm:ss.SSS"
            ].map { (format: String) -> NSDateFormatter in
                let formatter = NSDateFormatter()
                formatter.dateFormat = format
                return formatter
            }
            // Decoder for NSDate
            Decoders.addDecoder(clazz: NSDate.self) { (source: AnyObject) -> NSDate in
               if let sourceString = source as? String {
                    for formatter in formatters {
                        if let date = formatter.dateFromString(sourceString) {
                            return date
                        }
                    }

                }
                if let sourceInt = source as? Int {
                    // treat as a java date
                    return NSDate(timeIntervalSince1970: Double(sourceInt / 1000) )
                }
                fatalError("formatter failed to parse \(source)")
            } 

            // Decoder for [Category]
            Decoders.addDecoder(clazz: [Category].self) { (source: AnyObject) -> [Category] in
                return Decoders.decode(clazz: [Category].self, source: source)
            }
            // Decoder for Category
            Decoders.addDecoder(clazz: Category.self) { (source: AnyObject) -> Category in
                let sourceDictionary = source as! [NSObject:AnyObject]
                let instance = Category()
                instance.name = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["name"])
                instance.id = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["id"])
                instance.parent = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["parent"])
                return instance
            }


            // Decoder for [Error]
            Decoders.addDecoder(clazz: [Error].self) { (source: AnyObject) -> [Error] in
                return Decoders.decode(clazz: [Error].self, source: source)
            }
            // Decoder for Error
            Decoders.addDecoder(clazz: Error.self) { (source: AnyObject) -> Error in
                let sourceDictionary = source as! [NSObject:AnyObject]
                let instance = Error()
                instance.error = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["Error"])
                return instance
            }


            // Decoder for [EventRequest]
            Decoders.addDecoder(clazz: [EventRequest].self) { (source: AnyObject) -> [EventRequest] in
                return Decoders.decode(clazz: [EventRequest].self, source: source)
            }
            // Decoder for EventRequest
            Decoders.addDecoder(clazz: EventRequest.self) { (source: AnyObject) -> EventRequest in
                let sourceDictionary = source as! [NSObject:AnyObject]
                let instance = EventRequest()
                instance.url = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["url"])
                instance.serviceid = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["serviceid"])
                instance.postbody = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["postbody"])
                return instance
            }


            // Decoder for [InventoryGroup]
            Decoders.addDecoder(clazz: [InventoryGroup].self) { (source: AnyObject) -> [InventoryGroup] in
                return Decoders.decode(clazz: [InventoryGroup].self, source: source)
            }
            // Decoder for InventoryGroup
            Decoders.addDecoder(clazz: InventoryGroup.self) { (source: AnyObject) -> InventoryGroup in
                let sourceDictionary = source as! [NSObject:AnyObject]
                let instance = InventoryGroup()
                instance.name = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["name"])
                instance.items = Decoders.decodeOptional(clazz: Array.self, source: sourceDictionary["items"])
                return instance
            }


            // Decoder for [Item]
            Decoders.addDecoder(clazz: [Item].self) { (source: AnyObject) -> [Item] in
                return Decoders.decode(clazz: [Item].self, source: source)
            }
            // Decoder for Item
            Decoders.addDecoder(clazz: Item.self) { (source: AnyObject) -> Item in
                let sourceDictionary = source as! [NSObject:AnyObject]
                let instance = Item()
                instance.id = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["id"])
                instance.category = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["category"])
                instance.desc = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["desc"])
                instance.name = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["name"])
                instance.ordprice = Decoders.decodeOptional(clazz: Double.self, source: sourceDictionary["ordprice"])
                instance.price = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["price"])
                instance.variations = Decoders.decodeOptional(clazz: Array.self, source: sourceDictionary["variations"])
                instance.quantity = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["quantity"])
                instance.media = Decoders.decodeOptional(clazz: Array.self, source: sourceDictionary["media"])
                instance.buy = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["Buy"])
                return instance
            }


            // Decoder for [ItemRequest]
            Decoders.addDecoder(clazz: [ItemRequest].self) { (source: AnyObject) -> [ItemRequest] in
                return Decoders.decode(clazz: [ItemRequest].self, source: source)
            }
            // Decoder for ItemRequest
            Decoders.addDecoder(clazz: ItemRequest.self) { (source: AnyObject) -> ItemRequest in
                let sourceDictionary = source as! [NSObject:AnyObject]
                let instance = ItemRequest()
                instance.id = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["id"])
                instance.category = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["category"])
                instance.desc = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["desc"])
                instance.name = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["name"])
                instance.ordprice = Decoders.decodeOptional(clazz: Double.self, source: sourceDictionary["ordprice"])
                instance.price = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["price"])
                instance.quantity = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["quantity"])
                return instance
            }


            // Decoder for [Order]
            Decoders.addDecoder(clazz: [Order].self) { (source: AnyObject) -> [Order] in
                return Decoders.decode(clazz: [Order].self, source: source)
            }
            // Decoder for Order
            Decoders.addDecoder(clazz: Order.self) { (source: AnyObject) -> Order in
                let sourceDictionary = source as! [NSObject:AnyObject]
                let instance = Order()
                instance.orderId = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["order_id"])
                instance.infoEmail = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["info_email"])
                instance.infoFirst = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["info_first"])
                instance.infoLast = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["info_last"])
                instance.phone = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["phone"])
                instance.shipset = Decoders.decodeOptional(clazz: Bool.self, source: sourceDictionary["shipset"])
                instance.infoAdr1 = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["info_adr1"])
                instance.infoAdr2 = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["info_adr2"])
                instance.infoCty = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["info_cty"])
                instance.infoZip = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["info_zip"])
                instance.state = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["state"])
                instance.infoSadr1 = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["info_sadr1"])
                instance.infoSadr2 = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["info_sadr2"])
                instance.infoScty = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["info_scty"])
                instance.infoSzip = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["info_szip"])
                instance.sstate = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["sstate"])
                instance.taxAmount = Decoders.decodeOptional(clazz: Float.self, source: sourceDictionary["tax_amount"])
                instance.shippingAmount = Decoders.decodeOptional(clazz: Float.self, source: sourceDictionary["shipping_amount"])
                instance.amountTotal = Decoders.decodeOptional(clazz: Float.self, source: sourceDictionary["amount_total"])
                instance.itemIDs = Decoders.decodeOptional(clazz: Array.self, source: sourceDictionary["itemIDs"])
                return instance
            }


            // Decoder for [OrderRequest]
            Decoders.addDecoder(clazz: [OrderRequest].self) { (source: AnyObject) -> [OrderRequest] in
                return Decoders.decode(clazz: [OrderRequest].self, source: source)
            }
            // Decoder for OrderRequest
            Decoders.addDecoder(clazz: OrderRequest.self) { (source: AnyObject) -> OrderRequest in
                let sourceDictionary = source as! [NSObject:AnyObject]
                let instance = OrderRequest()
                instance.orderId = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["order_id"])
                instance.infoEmail = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["info_email"])
                instance.infoFirst = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["info_first"])
                instance.infoLast = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["info_last"])
                instance.phone = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["phone"])
                instance.shipset = Decoders.decodeOptional(clazz: Bool.self, source: sourceDictionary["shipset"])
                instance.infoAdr1 = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["info_adr1"])
                instance.infoAdr2 = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["info_adr2"])
                instance.infoCty = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["info_cty"])
                instance.infoZip = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["info_zip"])
                instance.state = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["state"])
                instance.infoSadr1 = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["info_sadr1"])
                instance.infoSadr2 = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["info_sadr2"])
                instance.infoScty = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["info_scty"])
                instance.infoSzip = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["info_szip"])
                instance.sstate = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["sstate"])
                instance.taxAmount = Decoders.decodeOptional(clazz: Float.self, source: sourceDictionary["tax_amount"])
                instance.shippingAmount = Decoders.decodeOptional(clazz: Float.self, source: sourceDictionary["shipping_amount"])
                instance.amountTotal = Decoders.decodeOptional(clazz: Float.self, source: sourceDictionary["amount_total"])
                return instance
            }


            // Decoder for [Response]
            Decoders.addDecoder(clazz: [Response].self) { (source: AnyObject) -> [Response] in
                return Decoders.decode(clazz: [Response].self, source: source)
            }
            // Decoder for Response
            Decoders.addDecoder(clazz: Response.self) { (source: AnyObject) -> Response in
                let sourceDictionary = source as! [NSObject:AnyObject]
                let instance = Response()
                instance.approved = Decoders.decodeOptional(clazz: Double.self, source: sourceDictionary["approved"])
                return instance
            }


            // Decoder for [Service]
            Decoders.addDecoder(clazz: [Service].self) { (source: AnyObject) -> [Service] in
                return Decoders.decode(clazz: [Service].self, source: source)
            }
            // Decoder for Service
            Decoders.addDecoder(clazz: Service.self) { (source: AnyObject) -> Service in
                let sourceDictionary = source as! [NSObject:AnyObject]
                let instance = Service()
                instance.name = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["name"])
                instance.desc = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["desc"])
                instance.price = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["price"])
                instance.event = Decoders.decodeOptional(clazz: EventRequest.self, source: sourceDictionary["event"])
                instance.recurpric = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["recurpric"])
                return instance
            }


            // Decoder for [ServiceRequest]
            Decoders.addDecoder(clazz: [ServiceRequest].self) { (source: AnyObject) -> [ServiceRequest] in
                return Decoders.decode(clazz: [ServiceRequest].self, source: source)
            }
            // Decoder for ServiceRequest
            Decoders.addDecoder(clazz: ServiceRequest.self) { (source: AnyObject) -> ServiceRequest in
                let sourceDictionary = source as! [NSObject:AnyObject]
                let instance = ServiceRequest()
                instance.name = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["name"])
                instance.desc = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["desc"])
                instance.price = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["price"])
                instance.recurpric = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["recurpric"])
                return instance
            }


            // Decoder for [Variation]
            Decoders.addDecoder(clazz: [Variation].self) { (source: AnyObject) -> [Variation] in
                return Decoders.decode(clazz: [Variation].self, source: source)
            }
            // Decoder for Variation
            Decoders.addDecoder(clazz: Variation.self) { (source: AnyObject) -> Variation in
                let sourceDictionary = source as! [NSObject:AnyObject]
                let instance = Variation()
                instance.name = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["name"])
                instance.priceChange = Decoders.decodeOptional(clazz: Double.self, source: sourceDictionary["priceChange"])
                instance.id = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["id"])
                return instance
            }
        }
    }
}
