//
//  User.swift
//  UsergridSDK
//
//  Created by Robert Walsh on 7/21/15.
//
/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  The ASF licenses this file to You
 * under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.  For additional information regarding
 * copyright in this work, please see the NOTICE file in the top level
 * directory of this distribution.
 *
 */

import Foundation

/// The completion block used for checking email and/or username availablity for new `UsergridUser` objects.
public typealias UsergridUserAvailabilityCompletion = (error: UsergridResponseError?, available:Bool) -> Void

/// The completion block used for changing the password of `UsergridUser` objects.
public typealias UsergridUserResetPasswordCompletion = (error: UsergridResponseError?, didSucceed:Bool) -> Void

/**
`UsergridUser` is a special subclass of `UsergridEntity` that supports functions and properties unique to users.
*/
public class UsergridUser : UsergridEntity {

    static let USER_ENTITY_TYPE = "user"

    // MARK: - Instance Properties -

    /// The `UsergridUserAuth` object if this user was authenticated.
    public var auth: UsergridUserAuth?

    /** 
    Property helper method for the `UsergridUser` objects `UsergridUserProperties.Name`.
    
    Unlike `UsergridEntity` objects, `UsergridUser`'s can change their name property which is why we provide a getter here.
    */
    override public var name: String? {
        set(name) { self[UsergridUserProperties.Name.stringValue] = name }
        get{ return super.name }
    }

    /// Property getter and setter helpers for the `UsergridUser` objects `UsergridUserProperties.Username`.
    public var username: String? {
        set(username) { self[UsergridUserProperties.Username.stringValue] = username }
        get { return self.getUserSpecificProperty(.Username) as? String }
    }

    /// Property getter and setter helpers for the `UsergridUser` objects `UsergridUserProperties.Password`.
    public var password: String? {
        set(password) { self[UsergridUserProperties.Password.stringValue] = password }
        get { return self.getUserSpecificProperty(.Password) as? String }
    }

    /// Property getter and setter helpers for the `UsergridUser` objects `UsergridUserProperties.Email`.
    public var email: String? {
        set(email) { self[UsergridUserProperties.Email.stringValue] = email }
        get { return self.getUserSpecificProperty(.Email) as? String }
    }

    /// Property getter and setter helpers for the `UsergridUser` objects `UsergridUserProperties.Age`.
    public var age: NSNumber? {
        set(age) { self[UsergridUserProperties.Age.stringValue] = age }
        get { return self.getUserSpecificProperty(.Age) as? NSNumber }
    }

    /// Property helper method to get the username or email of the `UsergridUser`.
    public var usernameOrEmail: String? { return self.username ?? self.email }

    /** 
    Property getter and setter helpers for the `UsergridUser` objects `UsergridUserProperties.Activated`.
    
    Indicates whether the user account has been activated or not.
    */
    public var activated: Bool {
        set(activated) { self[UsergridUserProperties.Activated.stringValue] = activated }
        get { return self.getUserSpecificProperty(.Activated) as? Bool ?? false }
    }

    /// Property getter and setter helpers for the `UsergridUser` objects `UsergridUserProperties.Disabled`.
    public var disabled: Bool {
        set(disabled) { self[UsergridUserProperties.Disabled.stringValue] = disabled }
        get { return self.getUserSpecificProperty(.Disabled) as? Bool ?? false }
    }

    /**
    Property getter and setter helpers for the `UsergridUser` objects `UsergridUserProperties.Picture`.
    
    URL path to user’s profile picture. Defaults to Gravatar for email address.
    */
    public var picture: String? {
        set(picture) { self[UsergridUserProperties.Picture.stringValue] = picture }
        get { return self.getUserSpecificProperty(.Picture) as? String }
    }

    /// The UUID or username property value if found.
    public var uuidOrUsername: String? { return self.uuid ?? self.username }

    // MARK: - Initialization -

    /**
    Designated initializer for `UsergridUser` objects.

    - parameter name: The name of the user.  Note this is different from the `username` property.

    - returns: A new instance of `UsergridUser`.
    */
    public init(name:String? = nil) {
        super.init(type: UsergridUser.USER_ENTITY_TYPE, name:name, propertyDict:nil)
    }

    /**
     The required public initializer for `UsergridEntity` subclasses.

     - parameter type:         The type associated with the `UsergridEntity` object.
     - parameter name:         The optional name associated with the `UsergridEntity` object.
     - parameter propertyDict: The optional property dictionary that the `UsergridEntity` object will start out with.

     - returns: A new `UsergridUser` object.
     */
    required public init(type: String, name: String?, propertyDict: [String : AnyObject]?) {
        super.init(type: type, name: name, propertyDict: propertyDict)
    }

    /**
    Designated initializer for `UsergridUser` objects.

    - parameter name:         The name of the user.  Note this is different from the `username` property.
    - parameter propertyDict: The optional property dictionary that the `UsergridEntity` object will start out with.

    - returns: A new instance of `UsergridUser`.
    */
    public init(name:String,propertyDict:[String:AnyObject]? = nil) {
        super.init(type: UsergridUser.USER_ENTITY_TYPE, name:name, propertyDict:propertyDict)
    }

    /**
     Convenience initializer for `UsergridUser` objects.

     - parameter name:     The name of the user.  Note this is different from the `username` property.
     - parameter email:    The user's email.
     - parameter password: The optional user's password.

     - returns: A new instance of `UsergridUser`.
     */
    public convenience init(name:String, email:String, password:String? = nil) {
        self.init(name:name,email:email,username:nil,password:password)
    }

    /**
     Convenience initializer for `UsergridUser` objects.

     - parameter email:    The user's email.
     - parameter password: The optional user's password.

     - returns: A new instance of `UsergridUser`.
     */
    public convenience init(email:String, password:String? = nil) {
        self.init(name:nil,email:email,username:nil,password:password)
    }

    /**
     Convenience initializer for `UsergridUser` objects.

     - parameter name:     The name of the user.  Note this is different from the `username` property.
     - parameter username: The username of the user.
     - parameter password: The optional user's password.

     - returns: A new instance of `UsergridUser`.
     */
    public convenience init(name:String, username:String, password:String? = nil) {
        self.init(name:name,email:nil,username:username,password:password)
    }

    /**
     Convenience initializer for `UsergridUser` objects.

     - parameter username: The username of the user.
     - parameter password: The optional user's password.

     - returns: A new instance of `UsergridUser`.
     */
    public convenience init(username:String, password:String? = nil) {
        self.init(name:nil,email:nil,username:username,password:password)
    }

    /**
     Convenience initializer for `UsergridUser` objects.

     - parameter name:     The optional name of the user.  Note this is different from the `username` property.
     - parameter email:    The optional user's email.
     - parameter username: The optional username of the user.
     - parameter password: The optional user's password.

     - returns: A new instance of `UsergridUser`.
     */
    public convenience init(name:String?, email:String?, username:String?, password:String? = nil) {
        self.init(name:name)
        self.email = email
        self.username = username
        self.password = password
    }

    // MARK: - NSCoding -

    /**
    NSCoding protocol initializer.

    - parameter aDecoder: The decoder.

    - returns: A decoded `UsergridUser` object.
    */
    required public init?(coder aDecoder: NSCoder) {
        self.auth = aDecoder.decodeObjectForKey("auth") as? UsergridUserAuth
        super.init(coder: aDecoder)
    }

    /**
     NSCoding protocol encoder.

     - parameter aCoder: The encoder.
     */
    public override func encodeWithCoder(aCoder: NSCoder) {
        aCoder.encodeObject(self.auth, forKey: "auth")
        super.encodeWithCoder(aCoder)
    }

    // MARK: - Class Methods -

    /**
    Checks the given email and/or username availablity for new `UsergridUser` objects using the shared instance of `UsergridClient`.

    - parameter email:      The optional email address.
    - parameter username:   The optional username.
    - parameter completion: The completion block.
    */
    public static func checkAvailable(email:String?, username:String?, completion:UsergridUserAvailabilityCompletion) {
        self.checkAvailable(Usergrid.sharedInstance, email: email, username: username, completion: completion)
    }

    /**
     Checks the given email and/or username availablity for new `UsergridUser` objects using with the given `UsergridClient`.

     - parameter client:     The client to use for checking availability.
     - parameter email:      The optional email address.
     - parameter username:   The optional username.
     - parameter completion: The completion block.
     */
    public static func checkAvailable(client: UsergridClient, email:String?, username:String?, completion:UsergridUserAvailabilityCompletion) {
        let query = UsergridQuery(USER_ENTITY_TYPE)
        if let emailValue = email {
            query.eq(UsergridUserProperties.Email.stringValue, value: emailValue)
        }
        if let usernameValue = username {
            query.or().eq(UsergridUserProperties.Username.stringValue, value: usernameValue)
        }
        client.GET(query) { (response) -> Void in
            completion(error: response.error, available: response.entity == nil)
        }
    }

    // MARK: - Instance Methods -

    /**
    Creates the user object in Usergrid if the user does not already exist with the shared instance of `UsergridClient`.

    - parameter completion: The optional completion block.
    */
    public func create(completion: UsergridResponseCompletion? = nil) {
        self.create(Usergrid.sharedInstance, completion: completion)
    }

    /**
    Creates the user object in Usergrid if the user does not already exist with the given `UsergridClient`.

    - parameter client:     The client to use for creation.
    - parameter completion: The optional completion block.
    */
    public func create(client: UsergridClient, completion: UsergridResponseCompletion? = nil) {
        client.POST(self,completion:completion)
    }

    /**
    Authenticates the specified user using the provided username and password with the shared instance of `UsergridClient`.

    While functionally similar to `UsergridClient.authenticateUser(auth)`, this method does not automatically assign this user to `UsergridClient.currentUser`:

    - parameter username:   The username.
    - parameter password:   The password.
    - parameter completion: The optional completion block.
    */
    public func login(username:String, password:String, completion: UsergridUserAuthCompletionBlock? = nil) {
        self.login(Usergrid.sharedInstance, username: username, password: password, completion: completion)
    }

    /**
    Authenticates the specified user using the provided username and password.

    While functionally similar to `UsergridClient.authenticateUser(auth)`, this method does not automatically assign this user to `UsergridClient.currentUser`:

    - parameter client:     The client to use for login.
    - parameter username:   The username.
    - parameter password:   The password.
    - parameter completion: The optional completion block.
    */
    public func login(client: UsergridClient, username:String, password:String, completion: UsergridUserAuthCompletionBlock? = nil) {
        let userAuth = UsergridUserAuth(username: username, password: password)
        client.authenticateUser(userAuth,setAsCurrentUser:false) { (auth, user, error) -> Void in
            self.auth = userAuth
            completion?(auth: userAuth, user: user, error: error)
        }
    }

     /**
     Changes the User's current password with the shared instance of `UsergridClient`.

     - parameter old:        The old password.
     - parameter new:        The new password.
     - parameter completion: The optional completion block.
     */
    public func resetPassword(old:String, new:String, completion:UsergridUserResetPasswordCompletion? = nil) {
        self.resetPassword(Usergrid.sharedInstance, old: old, new: new, completion: completion)
    }

    /**
     Changes the User's current password with the shared instance of `UsergridClient`.

     - parameter client:     The client to use for resetting the password.
     - parameter old:        The old password.
     - parameter new:        The new password.
     - parameter completion: The optional completion block
     */
    public func resetPassword(client: UsergridClient, old:String, new:String, completion:UsergridUserResetPasswordCompletion? = nil) {
        client.resetPassword(self, old: old, new: new, completion: completion)
    }

    /**
     Attmepts to reauthenticate using the user's `UsergridUserAuth` instance property with the shared instance of `UsergridClient`.

     - parameter completion: The optional completion block.
     */
    public func reauthenticate(completion: UsergridUserAuthCompletionBlock? = nil) {
        self.reauthenticate(Usergrid.sharedInstance, completion: completion)
    }

    /**
     Attmepts to reauthenticate using the user's `UsergridUserAuth` instance property.

     - parameter client:     The client to use for reauthentication.
     - parameter completion: The optional completion block.
     */
    public func reauthenticate(client: UsergridClient, completion: UsergridUserAuthCompletionBlock? = nil) {
        if let userAuth = self.auth {
            client.authenticateUser(userAuth, completion: completion)
        } else {
            let error = UsergridResponseError(errorName: "Invalid UsergridUserAuth.", errorDescription: "No UsergridUserAuth found on the UsergridUser.")
            completion?(auth: nil, user: self, error: error)
        }
    }

    /**
    Invalidates the user token locally and remotely.

    - parameter completion: The optional completion block.
    */
    public func logout(completion:UsergridResponseCompletion? = nil) {
        self.logout(Usergrid.sharedInstance,completion:completion)
    }

    /**
    Invalidates the user token locally and remotely.

    - parameter client:     The client to use for logout.
    - parameter completion: The optional completion block.
    */
    public func logout(client: UsergridClient, completion:UsergridResponseCompletion? = nil) {
        if self === client.currentUser {
            client.logoutCurrentUser(completion)
        } else if let uuidOrUsername = self.uuidOrUsername, accessToken = self.auth?.accessToken {
            client.logoutUser(uuidOrUsername, token: accessToken) { (response) in
                self.auth = nil
                completion?(response: response)
            }
        } else {
            completion?(response: UsergridResponse(client:client, errorName:"Logout Failed.", errorDescription:"UUID or Access Token not found on UsergridUser object."))
        }
    }

    /**
     A special convenience function that connects a `UsergridDevice` to this `UsergridUser` using the shared instance of `UsergridClient`.

     - parameter device:     The device to connect to.  If nil it will use the `UsergridDevice.sharedDevice` instance.
     - parameter completion: The optional completion block.
     */
    public func connectToDevice(device:UsergridDevice? = nil, completion:UsergridResponseCompletion? = nil) {
        self.connectToDevice(Usergrid.sharedInstance, device: device, completion: completion)
    }

    /**
     A special convenience function that connects a `UsergridDevice` to this `UsergridUser`.

     - parameter client:     The `UsergridClient` object to use for connecting.
     - parameter device:     The device to connect to.  If nil it will use the `UsergridDevice.sharedDevice` instance.
     - parameter completion: The optional completion block.
     */
    public func connectToDevice(client:UsergridClient, device:UsergridDevice? = nil, completion:UsergridResponseCompletion? = nil) {
        let deviceToConnect = device ?? UsergridDevice.sharedDevice
        guard let _ = deviceToConnect.uuidOrName
        else {
            completion?(response: UsergridResponse(client: client, errorName: "Device cannot be connected to User.", errorDescription: "Device has neither an UUID or name specified."))
            return
        }

        self.connect(client, relationship: "devices", toEntity: deviceToConnect, completion: completion)
    }

    /**
     A special convenience function that disconnects a `UsergridDevice` from this `UsergridUser` using the shared instance of `UsergridClient`.

     - parameter device:     The device to connect to.  If nil it will use the `UsergridDevice.sharedDevice` instance.
     - parameter completion: The optional completion block.
     */
    public func disconnectFromDevice(device:UsergridDevice? = nil, completion:UsergridResponseCompletion? = nil) {
        self.disconnectFromDevice(Usergrid.sharedInstance, device: device, completion: completion)
    }

    /**
     A special convenience function that disconnects a `UsergridDevice` from this `UsergridUser`.

     - parameter client:     The `UsergridClient` object to use for connecting.
     - parameter device:     The device to connect to.
     - parameter completion: The optional completion block.
     */
    public func disconnectFromDevice(client:UsergridClient, device:UsergridDevice? = nil, completion:UsergridResponseCompletion? = nil) {
        let deviceToDisconnectFrom = device ?? UsergridDevice.sharedDevice
        guard let _ = deviceToDisconnectFrom.uuidOrName
            else {
                completion?(response: UsergridResponse(client: client, errorName: "Device cannot be disconnected from User.", errorDescription: "Device has neither an UUID or name specified."))
                return
        }

        self.disconnect(client, relationship: "devices", fromEntity: deviceToDisconnectFrom, completion: completion)
    }

    private func getUserSpecificProperty(userProperty: UsergridUserProperties) -> AnyObject? {
        var propertyValue: AnyObject? = super[userProperty.stringValue]
        NSJSONReadingOptions.AllowFragments
        switch userProperty {
            case .Activated,.Disabled :
                propertyValue = propertyValue?.boolValue
            case .Age :
                propertyValue = propertyValue?.integerValue
            case .Name,.Username,.Password,.Email,.Picture :
                break
        }
        return propertyValue
    }

    /**
    Subscript for the `UsergridUser` class.

    - Warning: When setting a properties value must be a valid JSON object.

    - Example usage:
    ```
    let someName = usergridUser["name"]
    
    usergridUser["name"] = someName
    ```
    */
    override public subscript(propertyName: String) -> AnyObject? {
        get {
            if let userProperty = UsergridUserProperties.fromString(propertyName) {
                return self.getUserSpecificProperty(userProperty)
            } else {
                return super[propertyName]
            }
        }
        set(propertyValue) {
            super[propertyName] = propertyValue
        }
    }
}