<commit_before>//
//  UsergridAsset.swift
//  UsergridSDK
//
//  Created by <NAME> on 9/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

#if os(iOS) || os(watchOS) || os(tvOS)
import UIKit
import MobileCoreServices
#endif

/// The progress block used in `UsergridAsset` are being uploaded or downloaded.
public typealias UsergridAssetRequestProgress = (bytesFinished:Int64, bytesExpected: Int64) -> Void

/// The completion block used in `UsergridAsset` are finished uploading.
public typealias UsergridAssetUploadCompletion = (response:UsergridResponse,asset:UsergridAsset?, error: String?) -> Void

/// The completion block used in `UsergridAsset` are finished downloading.
public typealias UsergridAssetDownloadCompletion = (asset:UsergridAsset?, error: String?) -> Void

/**
As Usergrid supports storing binary assets, the SDKs are designed to make uploading assets easier and more robust. Attaching, uploading, and downloading assets is handled by the `UsergridEntity` class.

Unless defined, whenever possible, the content-type will be inferred from the data provided, and the attached file (if not already a byte-array representation) will be binary-encoded.
*/
public class UsergridAsset: NSObject, NSCoding {

    private static let DEFAULT_FILE_NAME = "file"

    // MARK: - Instance Properties -

    /// The filename to be used in the multipart/form-data request.
    public let filename: String

    /// Binary representation of the asset's data.
    public let data: NSData

    /// A representation of the folder location the asset was loaded from, if it was provided in the initialization.
    public let originalLocation: String?

    /// The Content-type of the asset to be used when defining content-type inside the multipart/form-data request.
    public var contentType: String

    ///  The content length of the assets data.
    public var contentLength: Int { return self.data.length }
    
    // MARK: - Initialization -

    /**
    Designated initializer for `UsergridAsset` objects.

    - parameter fileName:         The file name associated with the file data.
    - parameter data:             The data of the file.
    - parameter originalLocation: An optional original location of the file.
    - parameter contentType:      The content type of the file.

    - returns: A new instance of `UsergridAsset`.
    */
    public init(filename:String? = UsergridAsset.DEFAULT_FILE_NAME, data:NSData, originalLocation:String? = nil, contentType:String) {
        self.filename = filename ?? UsergridAsset.DEFAULT_FILE_NAME
        self.data = data
        self.originalLocation = originalLocation
        self.contentType = contentType
    }

    #if os(iOS) || os(watchOS) || os(tvOS)
    /**
    Convenience initializer for `UsergridAsset` objects dealing with image data.

    - parameter fileName:         The file name associated with the file data.
    - parameter image:            The `UIImage` object to upload.
    - parameter imageContentType: The content type of the `UIImage`

    - returns: A new instance of `UsergridAsset` if the data can be gathered from the passed in `UIImage`, otherwise nil.
    */
    public convenience init?(fileName:String? = UsergridAsset.DEFAULT_FILE_NAME, image:UIImage, imageContentType:UsergridImageContentType = .Png) {
        var imageData: NSData?
        switch(imageContentType) {
            case .Png :
                imageData = UIImagePNGRepresentation(image)
            case .Jpeg :
                imageData = UIImageJPEGRepresentation(image, 1.0)
        }
        if let assetData = imageData {
            self.init(filename:fileName,data:assetData,contentType:imageContentType.stringValue)
        } else {
            self.init(filename:"",data:NSData(),contentType:"")
            return nil
        }
    }
    #endif

    /**
    Convenience initializer for `UsergridAsset` objects dealing directly with files on disk.

    - parameter fileName:    The file name associated with the file data.
    - parameter fileURL:     The `NSURL` object associated with the file.
    - parameter contentType: The content type of the `UIImage`.  If not specified it will try to figure out the type and if it can't initialization will fail.

    - returns: A new instance of `UsergridAsset` if the data can be gathered from the passed in `NSURL`, otherwise nil.
    */
    public convenience init?(fileName:String? = UsergridAsset.DEFAULT_FILE_NAME, fileURL:NSURL, contentType:String? = nil) {
        if fileURL.isFileReferenceURL(), let assetData = NSData(contentsOfURL: fileURL) {
            var fileNameToUse = fileName
            if fileNameToUse != UsergridAsset.DEFAULT_FILE_NAME, let inferredFileName = fileURL.lastPathComponent {
                fileNameToUse = inferredFileName
            }
            if let fileContentType = contentType ?? UsergridAsset.MIMEType(fileURL) {
                self.init(filename:fileNameToUse,data:assetData,originalLocation:fileURL.absoluteString,contentType:fileContentType)
            } else {
                print("Usergrid Error: Failed to imply content type of the asset.")<commit_msg>Fixed bug with UsergridAsset init with fileUrl.<commit_after>//
//  UsergridAsset.swift
//  UsergridSDK
//
//  Created by <NAME> on 9/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

#if os(iOS) || os(watchOS) || os(tvOS)
import UIKit
import MobileCoreServices
#endif

/// The progress block used in `UsergridAsset` are being uploaded or downloaded.
public typealias UsergridAssetRequestProgress = (bytesFinished:Int64, bytesExpected: Int64) -> Void

/// The completion block used in `UsergridAsset` are finished uploading.
public typealias UsergridAssetUploadCompletion = (response:UsergridResponse,asset:UsergridAsset?, error: String?) -> Void

/// The completion block used in `UsergridAsset` are finished downloading.
public typealias UsergridAssetDownloadCompletion = (asset:UsergridAsset?, error: String?) -> Void

/**
As Usergrid supports storing binary assets, the SDKs are designed to make uploading assets easier and more robust. Attaching, uploading, and downloading assets is handled by the `UsergridEntity` class.

Unless defined, whenever possible, the content-type will be inferred from the data provided, and the attached file (if not already a byte-array representation) will be binary-encoded.
*/
public class UsergridAsset: NSObject, NSCoding {

    private static let DEFAULT_FILE_NAME = "file"

    // MARK: - Instance Properties -

    /// The filename to be used in the multipart/form-data request.
    public let filename: String

    /// Binary representation of the asset's data.
    public let data: NSData

    /// A representation of the folder location the asset was loaded from, if it was provided in the initialization.
    public let originalLocation: String?

    /// The Content-type of the asset to be used when defining content-type inside the multipart/form-data request.
    public var contentType: String

    ///  The content length of the assets data.
    public var contentLength: Int { return self.data.length }
    
    // MARK: - Initialization -

    /**
    Designated initializer for `UsergridAsset` objects.

    - parameter fileName:         The file name associated with the file data.
    - parameter data:             The data of the file.
    - parameter originalLocation: An optional original location of the file.
    - parameter contentType:      The content type of the file.

    - returns: A new instance of `UsergridAsset`.
    */
    public init(filename:String? = UsergridAsset.DEFAULT_FILE_NAME, data:NSData, originalLocation:String? = nil, contentType:String) {
        self.filename = filename ?? UsergridAsset.DEFAULT_FILE_NAME
        self.data = data
        self.originalLocation = originalLocation
        self.contentType = contentType
    }

    #if os(iOS) || os(watchOS) || os(tvOS)
    /**
    Convenience initializer for `UsergridAsset` objects dealing with image data.

    - parameter fileName:         The file name associated with the file data.
    - parameter image:            The `UIImage` object to upload.
    - parameter imageContentType: The content type of the `UIImage`

    - returns: A new instance of `UsergridAsset` if the data can be gathered from the passed in `UIImage`, otherwise nil.
    */
    public convenience init?(fileName:String? = UsergridAsset.DEFAULT_FILE_NAME, image:UIImage, imageContentType:UsergridImageContentType = .Png) {
        var imageData: NSData?
        switch(imageContentType) {
            case .Png :
                imageData = UIImagePNGRepresentation(image)
            case .Jpeg :
                imageData = UIImageJPEGRepresentation(image, 1.0)
        }
        if let assetData = imageData {
            self.init(filename:fileName,data:assetData,contentType:imageContentType.stringValue)
        } else {
            self.init(filename:"",data:NSData(),contentType:"")
            return nil
        }
    }
    #endif

    /**
    Convenience initializer for `UsergridAsset` objects dealing directly with files on disk.

    - parameter fileName:    The file name associated with the file data.
    - parameter fileURL:     The `NSURL` object associated with the file.
    - parameter contentType: The content type of the `UIImage`.  If not specified it will try to figure out the type and if it can't initialization will fail.

    - returns: A new instance of `UsergridAsset` if the data can be gathered from the passed in `NSURL`, otherwise nil.
    */
    public convenience init?(fileName:String? = UsergridAsset.DEFAULT_FILE_NAME, fileURL:NSURL, contentType:String? = nil) {
        if fileURL.fileURL, let assetData = NSData(contentsOfURL: fileURL) {
            var fileNameToUse = fileName
            if fileNameToUse != UsergridAsset.DEFAULT_FILE_NAME, let inferredFileName = fileURL.lastPathComponent {
                fileNameToUse = inferredFileName
            }
            if let fileContentType = contentType ?? UsergridAsset.MIMEType(fileURL) {
                self.init(filename:fileNameToUse,data:assetData,originalLocation:fileURL.absoluteString,contentType:fileContentType)
            } else {
                print("Usergrid Error: Failed to imply content type of the asset.")
{'fraction_non_alphanumeric': 0.07532118565790578, 'fraction_numerical': 0.002519103199261063, 'mean_word_length': 3.1730903994393835, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6255126', 'n_tokens_mistral': 3072, 'n_tokens_neox': 2999, 'n_words': 1203}