//
// Generated by SwagGen
// https://github.com/yonaskolb/SwagGen
//

import Foundation
import JSONUtilities

extension TBX.UserService {

    public enum UserServiceCreateToken {

      public static let service = APIService<Response>(id: "UserService.createToken", tag: "UserService", method: "POST", path: "/UserServices/token", hasBody: true)

      public class Request: APIRequest<Response> {

          public struct Options {

              /** The customer subscriber id */
              public var subscriberId: String

              /** The customer country code */
              public var country: String

              /** Type of Token */
              public var type: String

              /** Token expiration date */
              public var expiration: Date?

              /** Token credits */
              public var credits: Double?

              /** Extra data to device */
              public var attributes: String?

              public init(subscriberId: String, country: String, type: String, expiration: Date? = nil, credits: Double? = nil, attributes: String? = nil) {
                  self.subscriberId = subscriberId
                  self.country = country
                  self.type = type
                  self.expiration = expiration
                  self.credits = credits
                  self.attributes = attributes
              }
          }

          public var options: Options

          public init(options: Options) {
              self.options = options
              super.init(service: UserServiceCreateToken.service)
          }

          /// convenience initialiser so an Option doesn't have to be created
          public convenience init(subscriberId: String, country: String, type: String, expiration: Date? = nil, credits: Double? = nil, attributes: String? = nil) {
              let options = Options(subscriberId: subscriberId, country: country, type: type, expiration: expiration, credits: credits, attributes: attributes)
              self.init(options: options)
          }

          public override var parameters: [String: Any] {
              var params: JSONDictionary = [:]
              params["subscriberId"] = options.subscriberId
              params["country"] = options.country
              params["type"] = options.type
              if let expiration = options.expiration?.encode() {
                params["expiration"] = expiration
              }
              if let credits = options.credits {
                params["credits"] = credits
              }
              if let attributes = options.attributes {
                params["attributes"] = attributes
              }
              return params
          }
        }

        public enum Response: APIResponseValue, CustomStringConvertible, CustomDebugStringConvertible {
            public typealias SuccessType = TokenObject

            /** Request was successful */
            case status200(TokenObject)

            /** Bad Request  */
            case status400(ResponseError)

            /** Unauthorized  */
            case status401(ResponseError)

            /** Customer or Device not Found */
            case status404(ResponseError)

            /** Device was Logged Out or the customer not longer exists */
            case status410(ResponseError)

            public var success: TokenObject? {
                switch self {
                case .status200(let response): return response
                default: return nil
                }
            }

            public var failure: ResponseError? {
                switch self {
                case .status400(let response): return response
                case .status401(let response): return response
                case .status404(let response): return response
                case .status410(let response): return response
                default: return nil
                }
            }

            /// either success or failure value. Success is anything in the 200..<300 status code range
            public var responseResult: APIResponseResult<TokenObject, ResponseError> {
                if let successValue = success {
                    return .success(successValue)
                } else if let failureValue = failure {
                    return .failure(failureValue)
                } else {
                    fatalError("Response does not have success or failure response")
                }
            }

            public var response: Any {
                switch self {
                case .status200(let response): return response
                case .status400(let response): return response
                case .status401(let response): return response
                case .status404(let response): return response
                case .status410(let response): return response
                }
            }

            public var statusCode: Int {
              switch self {
              case .status200: return 200
              case .status400: return 400
              case .status401: return 401
              case .status404: return 404
              case .status410: return 410
              }
            }

            public var successful: Bool {
              switch self {
              case .status200: return true
              case .status400: return false
              case .status401: return false
              case .status404: return false
              case .status410: return false
              }
            }

            public init(statusCode: Int, data: Data) throws {
                switch statusCode {
                case 200: self = try .status200(JSONDecoder.decode(data: data))
                case 400: self = try .status400(JSONDecoder.decode(data: data))
                case 401: self = try .status401(JSONDecoder.decode(data: data))
                case 404: self = try .status404(JSONDecoder.decode(data: data))
                case 410: self = try .status410(JSONDecoder.decode(data: data))
                default: throw APIError.unexpectedStatusCode(statusCode: statusCode, data: data)
                }
            }

            public var description: String {
                return "\(statusCode) \(successful ? "success" : "failure")"
            }

            public var debugDescription: String {
                var string = description
                let responseString = "\(response)"
                if responseString != "()" {
                    string += "\n\(responseString)"
                }
                return string
            }
        }
    }
}
