///
/// Copyright (c) 2016 Dropbox, Inc. All rights reserved.
///
/// Auto-generated by Stone, do not modify.
///

import Foundation

/// Datatypes and serializers for the common namespace
open class Common {
    /// The PathRoot union
    public enum PathRoot: CustomStringConvertible {
        /// Paths are relative to the authenticating user's home namespace, whether or not that user belongs to a team.
        case home
        /// Paths are relative to the authenticating user's root namespace (This results in invalidRoot in PathRootError
        /// if the user's root namespace has changed.).
        case root(String)
        /// Paths are relative to given namespace id (This results in noPermission in PathRootError if you don't have
        /// access to this namespace.).
        case namespaceId(String)
        /// An unspecified error.
        case other

        public var description: String {
            return "\(SerializeUtil.prepareJSONForSerialization(PathRootSerializer().serialize(self)))"
        }
    }
    open class PathRootSerializer: JSONSerializer {
        public init() { }
        open func serialize(_ value: PathRoot) -> JSON {
            switch value {
                case .home:
                    var d = [String: JSON]()
                    d[".tag"] = .str("home")
                    return .dictionary(d)
                case .root(let arg):
                    var d = ["root": Serialization._StringSerializer.serialize(arg)]
                    d[".tag"] = .str("root")
                    return .dictionary(d)
                case .namespaceId(let arg):
                    var d = ["namespace_id": Serialization._StringSerializer.serialize(arg)]
                    d[".tag"] = .str("namespace_id")
                    return .dictionary(d)
                case .other:
                    var d = [String: JSON]()
                    d[".tag"] = .str("other")
                    return .dictionary(d)
            }
        }
        open func deserialize(_ json: JSON) -> PathRoot {
            switch json {
                case .dictionary(let d):
                    let tag = Serialization.getTag(d)
                    switch tag {
                        case "home":
                            return PathRoot.home
                        case "root":
                            let v = Serialization._StringSerializer.deserialize(d["root"] ?? .null)
                            return PathRoot.root(v)
                        case "namespace_id":
                            let v = Serialization._StringSerializer.deserialize(d["namespace_id"] ?? .null)
                            return PathRoot.namespaceId(v)
                        case "other":
                            return PathRoot.other
                        default:
                            return PathRoot.other
                    }
                default:
                    fatalError("Failed to deserialize")
            }
        }
    }

    /// The PathRootError union
    public enum PathRootError: CustomStringConvertible {
        /// The root namespace id in Dropbox-API-Path-Root header is not valid. The value of this error is use's latest
        /// root info.
        case invalidRoot(Common.RootInfo)
        /// You don't have permission to access the namespace id in Dropbox-API-Path-Root  header.
        case noPermission
        /// An unspecified error.
        case other

        public var description: String {
            return "\(SerializeUtil.prepareJSONForSerialization(PathRootErrorSerializer().serialize(self)))"
        }
    }
    open class PathRootErrorSerializer: JSONSerializer {
        public init() { }
        open func serialize(_ value: PathRootError) -> JSON {
            switch value {
                case .invalidRoot(let arg):
                    var d = ["invalid_root": Common.RootInfoSerializer().serialize(arg)]
                    d[".tag"] = .str("invalid_root")
                    return .dictionary(d)
                case .noPermission:
                    var d = [String: JSON]()
                    d[".tag"] = .str("no_permission")
                    return .dictionary(d)
                case .other:
                    var d = [String: JSON]()
                    d[".tag"] = .str("other")
                    return .dictionary(d)
            }
        }
        open func deserialize(_ json: JSON) -> PathRootError {
            switch json {
                case .dictionary(let d):
                    let tag = Serialization.getTag(d)
                    switch tag {
                        case "invalid_root":
                            let v = Common.RootInfoSerializer().deserialize(d["invalid_root"] ?? .null)
                            return PathRootError.invalidRoot(v)
                        case "no_permission":
                            return PathRootError.noPermission
                        case "other":
                            return PathRootError.other
                        default:
                            return PathRootError.other
                    }
                default:
                    fatalError("Failed to deserialize")
            }
        }
    }

    /// Information about current user's root.
    open class RootInfo: CustomStringConvertible {
        /// The namespace ID for user's root namespace. It will be the namespace ID of the shared team root if the user
        /// is member of a team with a separate team root. Otherwise it will be same as homeNamespaceId in RootInfo.
        public let rootNamespaceId: String
        /// The namespace ID for user's home namespace.
        public let homeNamespaceId: String
        public init(rootNamespaceId: String, homeNamespaceId: String) {
            stringValidator(pattern: "[-_0-9a-zA-Z:]+")(rootNamespaceId)
            self.rootNamespaceId = rootNamespaceId
            stringValidator(pattern: "[-_0-9a-zA-Z:]+")(homeNamespaceId)
            self.homeNamespaceId = homeNamespaceId
        }
        open var description: String {
            return "\(SerializeUtil.prepareJSONForSerialization(RootInfoSerializer().serialize(self)))"
        }
    }
    open class RootInfoSerializer: JSONSerializer {
        public init() { }
        open func serialize(_ value: RootInfo) -> JSON {
            var output = [ 
            "root_namespace_id": Serialization._StringSerializer.serialize(value.rootNamespaceId),
            "home_namespace_id": Serialization._StringSerializer.serialize(value.homeNamespaceId),
            ]
            switch value {
                case let team as Common.TeamRootInfo:
                    for (k, v) in Serialization.getFields(Common.TeamRootInfoSerializer().serialize(team)) {
                        output[k] = v
                    }
                    output[".tag"] = .str("team")
                case let user as Common.UserRootInfo:
                    for (k, v) in Serialization.getFields(Common.UserRootInfoSerializer().serialize(user)) {
                        output[k] = v
                    }
                    output[".tag"] = .str("user")
                default: fatalError("Tried to serialize unexpected subtype")
            }
            return .dictionary(output)
        }
        open func deserialize(_ json: JSON) -> RootInfo {
            switch json {
                case .dictionary(let dict):
                    let tag = Serialization.getTag(dict)
                    switch tag {
                        case "team":
                            return Common.TeamRootInfoSerializer().deserialize(json)
                        case "user":
                            return Common.UserRootInfoSerializer().deserialize(json)
                        default:
                            let rootNamespaceId = Serialization._StringSerializer.deserialize(dict["root_namespace_id"] ?? .null)
                            let homeNamespaceId = Serialization._StringSerializer.deserialize(dict["home_namespace_id"] ?? .null)
                            return RootInfo(rootNamespaceId: rootNamespaceId, homeNamespaceId: homeNamespaceId)
                    }
                default:
                    fatalError("Type error deserializing")
            }
        }
    }

    /// Root info when user is member of a team with a separate root namespace ID.
    open class TeamRootInfo: Common.RootInfo {
        /// The path for user's home directory under the shared team root.
        public let homePath: String
        public init(rootNamespaceId: String, homeNamespaceId: String, homePath: String) {
            stringValidator()(homePath)
            self.homePath = homePath
            super.init(rootNamespaceId: rootNamespaceId, homeNamespaceId: homeNamespaceId)
        }
        open override var description: String {
            return "\(SerializeUtil.prepareJSONForSerialization(TeamRootInfoSerializer().serialize(self)))"
        }
    }
    open class TeamRootInfoSerializer: JSONSerializer {
        public init() { }
        open func serialize(_ value: TeamRootInfo) -> JSON {
            let output = [ 
            "root_namespace_id": Serialization._StringSerializer.serialize(value.rootNamespaceId),
            "home_namespace_id": Serialization._StringSerializer.serialize(value.homeNamespaceId),
            "home_path": Serialization._StringSerializer.serialize(value.homePath),
            ]
            return .dictionary(output)
        }
        open func deserialize(_ json: JSON) -> TeamRootInfo {
            switch json {
                case .dictionary(let dict):
                    let rootNamespaceId = Serialization._StringSerializer.deserialize(dict["root_namespace_id"] ?? .null)
                    let homeNamespaceId = Serialization._StringSerializer.deserialize(dict["home_namespace_id"] ?? .null)
                    let homePath = Serialization._StringSerializer.deserialize(dict["home_path"] ?? .null)
                    return TeamRootInfo(rootNamespaceId: rootNamespaceId, homeNamespaceId: homeNamespaceId, homePath: homePath)
                default:
                    fatalError("Type error deserializing")
            }
        }
    }

    /// Root info when user is not member of a team or the user is a member of a team and the team does not have a
    /// separate root namespace.
    open class UserRootInfo: Common.RootInfo {
        open override var description: String {
            return "\(SerializeUtil.prepareJSONForSerialization(UserRootInfoSerializer().serialize(self)))"
        }
    }
    open class UserRootInfoSerializer: JSONSerializer {
        public init() { }
        open func serialize(_ value: UserRootInfo) -> JSON {
            let output = [ 
            "root_namespace_id": Serialization._StringSerializer.serialize(value.rootNamespaceId),
            "home_namespace_id": Serialization._StringSerializer.serialize(value.homeNamespaceId),
            ]
            return .dictionary(output)
        }
        open func deserialize(_ json: JSON) -> UserRootInfo {
            switch json {
                case .dictionary(let dict):
                    let rootNamespaceId = Serialization._StringSerializer.deserialize(dict["root_namespace_id"] ?? .null)
                    let homeNamespaceId = Serialization._StringSerializer.deserialize(dict["home_namespace_id"] ?? .null)
                    return UserRootInfo(rootNamespaceId: rootNamespaceId, homeNamespaceId: homeNamespaceId)
                default:
                    fatalError("Type error deserializing")
            }
        }
    }

}
