//
//  UsergridEntity.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
import CoreLocation

/**
`UsergridEntity` is the base class that contains a single Usergrid entity. 

`UsergridEntity` maintains a set of accessor properties for standard Usergrid schema properties (e.g. name, uuid), and supports helper methods for accessing any custom properties that might exist.
*/
public class UsergridEntity: NSObject, NSCoding {

    static private var subclassMappings: [String:UsergridEntity.Type] = [UsergridUser.USER_ENTITY_TYPE:UsergridUser.self,UsergridDevice.DEVICE_ENTITY_TYPE:UsergridDevice.self]

    // MARK: - Instance Properties -

    /// The property dictionary that stores the properties values of the `UsergridEntity` object.
    private var properties: [String : AnyObject] {
        didSet {
            if let fileMetaData = properties.removeValueForKey(UsergridFileMetaData.FILE_METADATA) as? [String:AnyObject] {
                self.fileMetaData = UsergridFileMetaData(fileMetaDataJSON: fileMetaData)
            } else {
                self.fileMetaData = nil
            }
        }
    }

    /// The `UsergridAsset` that contains the asset data.
    public var asset: UsergridAsset?

    /// The `UsergridFileMetaData` of this `UsergridEntity`.
    private(set) public var fileMetaData : UsergridFileMetaData?

    /// Property helper method for the `UsergridEntity` objects `UsergridEntityProperties.EntityType`.
    public var type: String { return self.getEntitySpecificProperty(.EntityType) as! String }

    /// Property helper method for the `UsergridEntity` objects `UsergridEntityProperties.UUID`.
    public var uuid: String? { return self.getEntitySpecificProperty(.UUID) as? String }

    /// Property helper method for the `UsergridEntity` objects `UsergridEntityProperties.Name`.
    public var name: String? { return self.getEntitySpecificProperty(.Name) as? String }

    /// Property helper method for the `UsergridEntity` objects `UsergridEntityProperties.Created`.
    public var created: NSDate? { return self.getEntitySpecificProperty(.Created) as? NSDate }

    /// Property helper method for the `UsergridEntity` objects `UsergridEntityProperties.Modified`.
    public var modified: NSDate? { return self.getEntitySpecificProperty(.Modified) as? NSDate }

    /// Property helper method for the `UsergridEntity` objects `UsergridEntityProperties.Location`.
    public var location: CLLocation? {
        get { return self.getEntitySpecificProperty(.Location) as? CLLocation }
        set(newLocation) { self[UsergridEntityProperties.Location.stringValue] = newLocation }
    }

    /// Property helper method to get the UUID or name of the `UsergridEntity`.
    public var uuidOrName: String? { return self.uuid ?? self.name }

    /// Tells you if this `UsergridEntity` has a type of `user`.
    public var isUser: Bool { return self is UsergridUser || self.type == UsergridUser.USER_ENTITY_TYPE }

    /// Tells you if there is an asset associated with this entity.
    public var hasAsset: Bool { return self.asset != nil || self.fileMetaData?.contentLength > 0 }

    /// The JSON object value.
    public var jsonObjectValue : [String:AnyObject] { return self.properties }

    /// The string value.
    public var stringValue : String { return NSString(data: try! NSJSONSerialization.dataWithJSONObject(self.jsonObjectValue, options: .PrettyPrinted), encoding: NSUTF8StringEncoding) as! String }

    /// The description.
    public override var description : String {
        return "Properties of Entity: \(stringValue)."
    }

    /// The debug description.
    public override var debugDescription : String {
        return "Properties of Entity: \(stringValue)."
    }

    // MARK: - Initialization -

    /**
    Designated initializer for `UsergridEntity` objects

    - 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 `UsergridEntity` object.
    */
    required public init(type:String, name:String? = nil, propertyDict:[String:AnyObject]? = nil) {
        self.properties = propertyDict ?? [:]
        super.init()
        if self is UsergridUser {
            self.properties[UsergridEntityProperties.EntityType.stringValue] = UsergridUser.USER_ENTITY_TYPE
        } else if self is UsergridDevice {
            self.properties[UsergridEntityProperties.EntityType.stringValue] = UsergridDevice.DEVICE_ENTITY_TYPE
        } else {
            self.properties[UsergridEntityProperties.EntityType.stringValue] = type
        }
        if let entityName = name {
            self.properties[UsergridEntityProperties.Name.stringValue] = entityName
        }
    }

    internal func copyInternalsFromEntity(entity:UsergridEntity) {
        self.properties = entity.properties
    }

    /**
     Used for custom mapping subclasses to a given `Usergrid` type.

     - parameter type:       The type of the `Usergrid` object.
     - parameter toSubclass: The subclass `UsergridEntity.Type` to map it to.
     */
    public static func mapCustomType(type:String,toSubclass:UsergridEntity.Type) {
        UsergridEntity.subclassMappings[type] = toSubclass
    }

    /**
    Class convenience constructor for creating `UsergridEntity` objects dynamically.

    - parameter jsonDict: A valid JSON dictionary which must contain at the very least a value for the `type` key.

    - returns: A `UsergridEntity` object provided that the `type` key within the dictionay exists. Otherwise nil.
    */
    public class func entity(jsonDict jsonDict: [String:AnyObject]) -> UsergridEntity? {
        if let type = jsonDict[UsergridEntityProperties.EntityType.stringValue] as? String {
            if let mapping = UsergridEntity.subclassMappings[type] {
                return mapping.init(type: type,propertyDict:jsonDict)
            } else {
                return UsergridEntity(type:type, propertyDict:jsonDict)
            }
        } else {
            return nil
        }
    }

    /**
    Class convenience constructor for creating multiple `UsergridEntity` objects dynamically.

    - parameter entitiesJSONArray: An array which contains dictionaries that are used to create the `UsergridEntity` objects.

    - returns: An array of `UsergridEntity`.
    */
    public class func entities(jsonArray entitiesJSONArray: [[String:AnyObject]]) -> [UsergridEntity] {
        var entityArray : [UsergridEntity] = []
        for entityJSONDict in entitiesJSONArray {
            if let entity = UsergridEntity.entity(jsonDict:entityJSONDict) {
                entityArray.append(entity)
            }
        }
        return entityArray
    }

    // MARK: - NSCoding -

    /**
    NSCoding protocol initializer.

    - parameter aDecoder: The decoder.

    - returns: A decoded `UsergridUser` object.
    */
    required public init?(coder aDecoder: NSCoder) {
        guard let properties = aDecoder.decodeObjectForKey("properties") as? [String:AnyObject]
            else {
                self.properties = [:]
                super.init()
                return nil
        }
        self.properties = properties
        self.fileMetaData = aDecoder.decodeObjectForKey("fileMetaData") as? UsergridFileMetaData
        self.asset = aDecoder.decodeObjectForKey("asset") as? UsergridAsset
        super.init()
    }

    /**
     NSCoding protocol encoder.

     - parameter aCoder: The encoder.
     */
    public func encodeWithCoder(aCoder: NSCoder) {
        aCoder.encodeObject(self.properties, forKey: "properties")
        aCoder.encodeObject(self.fileMetaData, forKey: "fileMetaData")
        aCoder.encodeObject(self.asset, forKey: "asset")
    }

    // MARK: - Property Manipulation -

    /**
    Subscript for the `UsergridEntity` class.
    
    - Example usage:
        ```
        let propertyValue = usergridEntity["propertyName"]
        usergridEntity["propertyName"] = propertyValue
        ```
    */
    public subscript(propertyName: String) -> AnyObject? {
        get {
            if let entityProperty = UsergridEntityProperties.fromString(propertyName) {
                return self.getEntitySpecificProperty(entityProperty)
            } else {
                let propertyValue = self.properties[propertyName]
                if propertyValue === NSNull() { // Let's just return nil for properties that have been removed instead of NSNull
                    return nil
                } else {
                    return propertyValue
                }
            }
        }
        set(propertyValue) {
            if let value = propertyValue {
                if let entityProperty = UsergridEntityProperties.fromString(propertyName) {
                    if entityProperty.isMutableForEntity(self) {
                        if entityProperty == .Location {
                            if let location = value as? CLLocation {
                                properties[propertyName] = [ENTITY_LATITUDE:location.coordinate.latitude,
                                                            ENTITY_LONGITUDE:location.coordinate.longitude]
                            } else if let location = value as? CLLocationCoordinate2D {
                                properties[propertyName] = [ENTITY_LATITUDE:location.latitude,
                                                            ENTITY_LONGITUDE:location.longitude]
                            } else if let location = value as? [String:Double] {
                                if let lat = location[ENTITY_LATITUDE], long = location[ENTITY_LONGITUDE] {
                                    properties[propertyName] = [ENTITY_LATITUDE:lat,
                                                                ENTITY_LONGITUDE:long]
                                }
                            }
                        } else {
                            properties[propertyName] = value
                        }
                    }
                } else {
                    properties[propertyName] = value
                }
            } else { // If the property value is nil we assume they wanted to remove the property.

                // We set the value for this property to Null so that when a PUT is performed on the entity the property will actually be removed from the Entity on Usergrid
                if let entityProperty = UsergridEntityProperties.fromString(propertyName){
                    if entityProperty.isMutableForEntity(self) {
                        properties[propertyName] = NSNull()
                    }
                } else {
                    properties[propertyName] = NSNull()
                }
            }
        }
    }

    /**
    Updates a properties value for the given property name.

    - parameter name:  The name of the property.
    - parameter value: The value to update to.
    */
    public func putProperty(name:String,value:AnyObject?) {
        self[name] = value
    }

    /**
    Updates a set of properties that are within the given properties dictionary.

    - parameter properties: The property dictionary containing the properties names and values.
    */
    public func putProperties(properties:[String:AnyObject]) {
        for (name,value) in properties {
            self.putProperty(name, value: value)
        }
    }

    /**
    Removes the property for the given property name.

    - parameter name: The name of the property.
    */
    public func removeProperty(name:String) {
        self[name] = nil
    }

    /**
    Removes the properties with the names within the propertyNames array

    - parameter propertyNames: An array of property names.
    */
    public func removeProperties(propertyNames:[String]) {
        for name in propertyNames {
            self.removeProperty(name)
        }
    }

    /**
    Appends the given value to the end of the properties current value.

    - parameter name:  The name of the property.
     - parameter value: The value or an array of values to append.
    */
    public func append(name:String, value:AnyObject) {
        self.insertArray(name, values:value as? [AnyObject] ?? [value], index: Int.max)
    }

    /**
    Inserts the given value at the given index within the properties current value.

    - parameter name:  The name of the property.
    - parameter index: The index to insert at.
    - parameter value: The value or an array of values to insert.
    */
    public func insert(name:String, value:AnyObject, index:Int = 0) {
        self.insertArray(name, values:value as? [AnyObject] ?? [value], index: index)
    }

    /**
    Inserts an array of property values at a given index within the properties current value.

    - parameter name:   The name of the property
    - parameter index:  The index to insert at.
    - parameter values: The values to insert.
    */
    private func insertArray(name:String,values:[AnyObject], index:Int = 0) {
        if let propertyValue = self[name] {
            if let arrayValue = propertyValue as? [AnyObject] {
                var arrayOfValues = arrayValue
                if  index > arrayValue.count {
                    arrayOfValues.appendContentsOf(values)
                } else {
                    arrayOfValues.insertContentsOf(values, at: index)
                }
                self[name] = arrayOfValues
            } else {
                if index > 0 {
                    self[name] = [propertyValue] + values
                } else {
                    self[name] = values + [propertyValue]
                }
            }
        } else {
            self[name] = values
        }
    }

    /**
    Removes the last value of the properties current value.

    - parameter name: The name of the property.
    */
    public func pop(name:String) {
        if let arrayValue = self[name] as? [AnyObject] where arrayValue.count > 0 {
            var arrayOfValues = arrayValue
            arrayOfValues.removeLast()
            self[name] = arrayOfValues
        }
    }

    /**
    Removes the first value of the properties current value.

    - parameter name: The name of the property.
    */
    public func shift(name:String) {
        if let arrayValue = self[name] as? [AnyObject] where arrayValue.count > 0 {
            var arrayOfValues = arrayValue
            arrayOfValues.removeFirst()
            self[name] = arrayOfValues
        }
    }

    private func getEntitySpecificProperty(entityProperty: UsergridEntityProperties) -> AnyObject? {
        var propertyValue: AnyObject? = nil
        switch entityProperty {
        case .UUID,.EntityType,.Name :
            propertyValue = self.properties[entityProperty.stringValue]
        case .Created,.Modified :
            if let utcTimeStamp = self.properties[entityProperty.stringValue] as? Int {
                propertyValue = NSDate(utcTimeStamp: utcTimeStamp.description)
            }
        case .Location :
            if let locationDict = self.properties[entityProperty.stringValue] as? [String:Double], lat = locationDict[ENTITY_LATITUDE], long = locationDict[ENTITY_LONGITUDE] {
                propertyValue = CLLocation(latitude: lat, longitude: long)
            }
        }
        return propertyValue
    }

    // MARK: - CRUD Convenience Methods -

    /**
    Performs a GET on the `UsergridEntity` using the shared instance of `UsergridClient`.

    - parameter completion: An optional completion block that, if successful, will contain the reloaded `UsergridEntity` object.
    */
    public func reload(completion: UsergridResponseCompletion? = nil) {
        self.reload(Usergrid.sharedInstance, completion: completion)
    }

    /**
    Performs a GET on the `UsergridEntity`.

    - parameter client:     The client to use when reloading.
    - parameter completion: An optional completion block that, if successful, will contain the reloaded `UsergridEntity` object.
    */
    public func reload(client:UsergridClient, completion: UsergridResponseCompletion? = nil) {
        if let uuidOrName = self.uuidOrName {
            client.GET(self.type, uuidOrName: uuidOrName) { (response) -> Void in
                if let responseEntity = response.entity {
                    self.copyInternalsFromEntity(responseEntity)
                }
                completion?(response: response)
            }
        } else {
            completion?(response: UsergridResponse(client: client, errorName: "Entity cannot be reloaded.", errorDescription: "Entity has neither an UUID or name specified."))
        }
    }

    /**
    Performs a PUT (or POST if no UUID is found) on the `UsergridEntity` using the shared instance of `UsergridClient`.

    - parameter completion: An optional completion block that, if successful, will contain the updated/saved `UsergridEntity` object.
    */
    public func save(completion: UsergridResponseCompletion? = nil) {
        self.save(Usergrid.sharedInstance, completion: completion)
    }

    /**
    Performs a PUT (or POST if no UUID is found) on the `UsergridEntity`.

    - parameter client:     The client to use when saving.
    - parameter completion: An optional completion block that, if successful, will contain the updated/saved `UsergridEntity` object.
    */
    public func save(client:UsergridClient, completion: UsergridResponseCompletion? = nil) {
        if let _ = self.uuid { // If UUID exists we PUT otherwise POST
            client.PUT(self, completion: { (response) -> Void in
                if let responseEntity = response.entity {
                    self.copyInternalsFromEntity(responseEntity)
                }
                completion?(response: response)
            })
        } else {
            client.POST(self, completion: { (response) -> Void in
                if let responseEntity = response.entity {
                    self.copyInternalsFromEntity(responseEntity)
                }
                completion?(response: response)
            })
        }
    }

    /**
    Performs a DELETE on the `UsergridEntity` using the shared instance of the `UsergridClient`.

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

    /**
    Performs a DELETE on the `UsergridEntity`.

    - parameter client:     The client to use when removing.
    - parameter completion: An optional completion block.
    */
    public func remove(client:UsergridClient, completion: UsergridResponseCompletion? = nil) {
        client.DELETE(self, completion: completion)
    }

    // MARK: - Asset Management -

    /**
    Uploads the given `UsergridAsset` and the data within it and creates an association between this `UsergridEntity` with the given `UsergridAsset` using the shared instance of `UsergridClient`.

    - parameter asset:      The `UsergridAsset` object to upload.
    - parameter progress:   An optional progress block to keep track of upload progress.
    - parameter completion: An optional completion block.
    */
    public func uploadAsset(asset:UsergridAsset, progress:UsergridAssetRequestProgress? = nil, completion:UsergridAssetUploadCompletion? = nil) {
        Usergrid.sharedInstance.uploadAsset(self, asset: asset, progress:progress, completion:completion)
    }

    /**
    Uploads the given `UsergridAsset` and the data within it and creates an association between this `UsergridEntity` with the given `UsergridAsset`.

    - parameter client:     The client to use when uploading.
    - parameter asset:      The `UsergridAsset` object to upload.
    - parameter progress:   An optional progress block to keep track of upload progress.
    - parameter completion: An optional completion block.
    */
    public func uploadAsset(client:UsergridClient, asset:UsergridAsset, progress:UsergridAssetRequestProgress? = nil, completion:UsergridAssetUploadCompletion? = nil) {
        client.uploadAsset(self, asset: asset, progress:progress, completion:completion)
    }

    /**
    Downloads the `UsergridAsset` that is associated with this `UsergridEntity` using the shared instance of `UsergridClient`.

    - parameter contentType: The content type of the data to load.
    - parameter progress:    An optional progress block to keep track of download progress.
    - parameter completion:  An optional completion block.
    */
    public func downloadAsset(contentType:String, progress:UsergridAssetRequestProgress? = nil, completion:UsergridAssetDownloadCompletion? = nil) {
        Usergrid.sharedInstance.downloadAsset(self, contentType: contentType, progress:progress, completion: completion)
    }

    /**
    Downloads the `UsergridAsset` that is associated with this `UsergridEntity`.

    - parameter client:      The client to use when uploading.
    - parameter contentType: The content type of the data to load.
    - parameter progress:    An optional progress block to keep track of download progress.
    - parameter completion:  An optional completion block.
    */
    public func downloadAsset(client:UsergridClient, contentType:String, progress:UsergridAssetRequestProgress? = nil, completion:UsergridAssetDownloadCompletion? = nil) {
        client.downloadAsset(self, contentType: contentType, progress:progress, completion: completion)
    }

    // MARK: - Connection Management -

    /**
    Creates a relationship between this `UsergridEntity` and the given entity using the shared instance of `UsergridClient`.

    - parameter relationship: The relationship type.
    - parameter toEntity:     The entity to connect.
    - parameter completion:   An optional completion block.
    */
    public func connect(relationship:String, toEntity:UsergridEntity, completion: UsergridResponseCompletion? = nil) {
        Usergrid.sharedInstance.connect(self, relationship: relationship, to: toEntity, completion: completion)
    }

    /**
    Creates a relationship between this `UsergridEntity` and the given entity.

    - parameter client:       The client to use when connecting.
    - parameter relationship: The relationship type.
    - parameter toEntity:     The entity to connect.
    - parameter completion:   An optional completion block.
    */
    public func connect(client:UsergridClient, relationship:String, toEntity:UsergridEntity, completion: UsergridResponseCompletion? = nil) {
        client.connect(self, relationship: relationship, to: toEntity, completion: completion)
    }

    /**
    Removes a relationship between this `UsergridEntity` and the given entity using the shared instance of `UsergridClient`.

    - parameter relationship: The relationship type.
    - parameter fromEntity:   The entity to disconnect.
    - parameter completion:   An optional completion block.
    */
    public func disconnect(relationship:String, fromEntity:UsergridEntity, completion: UsergridResponseCompletion? = nil) {
        Usergrid.sharedInstance.disconnect(self, relationship: relationship, from: fromEntity, completion: completion)
    }

    /**
    Removes a relationship between this `UsergridEntity` and the given entity.

    - parameter client:       The client to use when disconnecting.
    - parameter relationship: The relationship type.
    - parameter fromEntity:   The entity to disconnect.
    - parameter completion:   An optional completion block.
    */
    public func disconnect(client:UsergridClient, relationship:String, fromEntity:UsergridEntity, completion: UsergridResponseCompletion? = nil) {
        client.disconnect(self, relationship: relationship, from: fromEntity, completion: completion)
    }

    /**
    Gets the `UsergridEntity` objects, if any, which are connected via the relationship using the shared instance of `UsergridClient`.

    - parameter direction:      The direction of the connection.
    - parameter relationship:   The relationship type.
    - parameter query:          The optional query.
    - parameter completion:     An optional completion block.
    */
    public func getConnections(direction:UsergridDirection, relationship:String, query:UsergridQuery?, completion:UsergridResponseCompletion? = nil) {
        Usergrid.sharedInstance.getConnections(direction, entity: self, relationship: relationship, query:query, completion: completion)
    }

    /**
    Gets the `UsergridEntity` objects, if any, which are connected via the relationship.

    - parameter client:       The client to use when getting the connected `UsergridEntity` objects.
    - parameter direction:    The direction of the connection.
    - parameter relationship: The relationship type.
    - parameter query:        The optional query.
    - parameter completion:   An optional completion block.
    */
    public func getConnections(client:UsergridClient, direction:UsergridDirection, relationship:String, query:UsergridQuery?, completion:UsergridResponseCompletion? = nil) {
        client.getConnections(direction, entity: self, relationship: relationship, query:query, completion: completion)
    }
}