             return bluemixConfig.remoteBaseRequestURL
         }
     }
-    
+
+}
+
+// MARK: - Methods related to getting/creating users
+extension BluemixDataManager {
+    
+    /**
+     Method gets user by id and will return the parsed response in the result callback
+     
+     - parameter userId: String
+     - parameter result: (user : User?, error : BlueMixDataManagerError?) -> ()
+     */
+    func getUserById(userId : String, result: (user : User?, error : BlueMixDataManagerError?) -> ()){
+        
+        let requestURL = getBluemixBaseRequestURL() + "/" + kUsersEndPoint + "/" + userId
+        
+        let request = Request(url: requestURL, method: HttpMethod.GET)
+        
+        request.sendWithCompletionHandler { (response, error) -> Void in
+            //error
+            if(error != nil){
+                if let response = response,
+                    let statusCode = response.statusCode {
+                    
+                    //user does not exist
+                    if(statusCode == 404){
+                        result(user: nil, error: BlueMixDataManagerError.UserDoesNotExist)
+                    }
+                        //any other error code means that it was a connection failure
+                    else{
+                        result(user: nil, error: BlueMixDataManagerError.ConnectionFailure)
+                    }
+                    
+                }
+                    //connection failure
+                else{
+                    result(user: nil, error: BlueMixDataManagerError.ConnectionFailure)
+                }
+            }
+                //No error
+            else {
+                //success
+                if let user = User(response) {
+                    result(user: user, error: nil)
+                    print ("Success :: \(response?.responseText)")
+                }
+                    //can't parse response - error
+                else {
+                    result(user: nil, error: BlueMixDataManagerError.ConnectionFailure)
+                }
+            }
+        }
+    }
+    
+    
+    /**
+     Method creates a new user and returns the parsed response in the result callback
+     
+     - parameter userId: String
+     - parameter name:   String
+     - parameter result: ((user : User?) -> ())
+     */
+    private func createNewUser(userId : String, name : String, result : ((user : User?) -> ())){
+        
+        let requestURL = getBluemixBaseRequestURL() + "/" + kUsersEndPoint
+        
+        let request = Request(url: requestURL, method: HttpMethod.POST)
+        
+        let json = ["_id": userId, "name": name]
+        
+        do{
+            let jsonData = try NSJSONSerialization.dataWithJSONObject(json, options: .PrettyPrinted)
+            
+            request.sendData(jsonData, completionHandler: { (response, error) -> Void in
+                if let error = error {
+                    result(user: nil)
+                    print ("Error  Creating New User :: \(error)")
+                } else {
+                    if let user = User(response) {
+                        result(user: user)
+                        print ("Success :: \(response?.responseText)")
+                    } else {
+                        result(user: nil)
+                        print("Response didn't contain all the necessary values")
+                    }
+                }
+            })
+            
+        } catch {
+            result(user: nil)
+            
+        }
+        
+    }
+    
+    
+    /**
+     Method checks to see if a user already exists, if the user doesn't exist then it creates a new user. It will return the parsed response in the callback parameter
+     
+     - parameter userId:   String
+     - parameter name:     String
+     - parameter callback: ((success : Bool) -> ())
+     */
+    func checkIfUserAlreadyExistsIfNotCreateNewUser(userId : String, name : String, callback : ((success : Bool) -> ())){
+        
+        getUserById(userId, result: { (user, error) in
+            
+            if let error = error {
+                
+                //user does not exist so create new user
+                if(error == BlueMixDataManagerError.UserDoesNotExist){
+                    self.createNewUser(userId, name: name, result: { user in
+                        
+                        if(user != nil){
+                            callback(success: true)
+                        }
+                        else{
+                            callback(success: false)
+                        }
+                        
+                    })
+                }
+                else if(error == BlueMixDataManagerError.ConnectionFailure){
+                    callback(success: false)
+                }
+            }
+            else {
+                callback(success: true)
+            }
+            
+        })
+    }
+    
+}
+
+// MARK: - Methods related to gettings images
+extension BluemixDataManager {
+    
+    /**
+     Method gets all the images posted on BluePic. When this request begins, the GetAllImagesStarted BluemixDataManagerNotification is sent out to the app. When the images have been successfully received, the ImagesRefreshed BluemixDataManagerNotification will be sent out
+     */
+    func getImages(){
+        
+        NSNotificationCenter.defaultCenter().postNotificationName(BluemixDataManagerNotification.GetAllImagesStarted.rawValue, object: nil)
+        
+        let requestURL = getBluemixBaseRequestURL() + "/" + kImagesEndPoint
+        let request = Request(url: requestURL, method: HttpMethod.GET)
+        
+        self.getImages(request) { images in
+            
+            if let images = images {
+                self.images = images
+                self.hasReceievedInitialImages = true
+                NSNotificationCenter.defaultCenter().postNotificationName(BluemixDataManagerNotification.ImagesRefreshed.rawValue, object: nil)
+            }
+        }
+    }
+    
+    /**
+     Method gets all the images by the specified tags in the tags parameter. When a response is receieved, we pass back the images we receive in the callback parameter
+     
+     - parameter tags:     [String]
+     - parameter callback: (images : [Image]?)->()
+     */
+    func getImagesByTags(tags: [String], callback : (images : [Image]?)->()) {
+        
+        var requestURL = getBluemixBaseRequestURL() + "/" + kImagesEndPoint + "?tag="
+        for (index, tag) in tags.enumerate() {
+            
+            guard let encodedTag = tag.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet()) else {
+                print("Failed to encode search tag")
+                continue
+            }
+            
+            if index == 0 {
+                requestURL.appendContentsOf(encodedTag.lowercaseString)
+            } else {
+                requestURL.appendContentsOf(",\(encodedTag.lowercaseString)")
+            }
+        }
+        let request = Request(url: requestURL, method: HttpMethod.GET)
+        
+        self.getImages(request) { images in
+            callback(images: images)
+        }
+        
+    }
+    
+    /**
+     Helper method to getImages and getImagesByTags method. It makes the request and then parses the response into an image array, then passes back response in result parameter
+     
+     - parameter request: Request
+     - parameter result:  (images : [Image]?)-> ()
+     */
+    func getImages(request: Request, result : (images : [Image]?)-> ()){
+        
+        request.sendWithCompletionHandler { (response, error) -> Void in
+            if let error = error {
+                result(images: nil)
+                print ("Error :: \(error)")
+            } else {
+                let images = self.parseGetImagesResponse(response, userId: nil, usersName: nil)
+                result(images: images)
+            }
+        }
+        
+    }
+    
+    
+    /**
+     Method parses the getImages response and returns an array of images
+     
+     - parameter response:  Response?
+     - parameter userId:    String?
+     - parameter usersName: String?
+     
+     - returns: [Image]
+     */
+    private func parseGetImagesResponse(response : Response?, userId : String?, usersName : String?) -> [Image]{
+        var images = [Image]()
+        
+        if let dict = Utils.convertResponseToDictionary(response),
+            let records = dict["records"] as? [[String:AnyObject]]{
+            
+            for var record in records {
+                
+                if let userId = userId, let usersName = usersName {
+                    
+                    var user = [String : AnyObject]()
+                    user["name"] = usersName
+                    user["_id"] = userId
+                    record["user"] = user
+                }
+                
+                if let image = Image(record){
+                    images.append(image)
+                }
+            }
+            
+        }
+        return images
+    }
+}
+
+// MARK: - Methods related to image uploading
+extension BluemixDataManager {
+    
+    /**
+     Method posts a new image. It will send the ImageUploadBegan notification when the image upload begins. It will send the ImageUploadSuccess notification when the image uploads successfully. For all other errors it will send out the ImageUploadFailure notification.
+     
+     - parameter image: Image
+     */
+    func postNewImage(image : Image){
+        
+        addImageToImagesCurrentlyUploading(image)
+        
+        NSNotificationCenter.defaultCenter().postNotificationName(BluemixDataManagerNotification.ImageUploadBegan.rawValue, object: nil)
+        
+        guard let facebookId = CurrentUser.facebookUserId, uiImage = image.image, imageData = UIImagePNGRepresentation(uiImage) else {
+            print("We don't have all the info necessary to post this image")
+            NSNotificationCenter.defaultCenter().postNotificationName(BluemixDataManagerNotification.ImageUploadFailure.rawValue, object: nil)
+            return
+        }
+        
+        let tempURL = getBluemixBaseRequestURL() + "/" + kUsersEndPoint + "/" + facebookId + "/" + kImagesEndPoint + "/" + image.fileName + "/" + image.caption + "/" + "\(image.width)" + "/" + "\(image.height)" + "/" + image.location.latitude + "/" + image.location.longitude + "/" + image.location.name
+        
+        guard let requestURL = tempURL.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet()) else {
+            print("Failed to encode request URL")
+            NSNotificationCenter.defaultCenter().postNotificationName(BluemixDataManagerNotification.ImageUploadFailure.rawValue, object: nil)
+            return
+        }
+        
+        let request = Request(url: requestURL, method: HttpMethod.POST)
+        
+        request.headers = ["Content-Type" : "image/png"]
+        
+        request.sendData(imageData, completionHandler: { (response, error) -> Void in
+            
+            //failure
+            if(error != nil){
+                
+                self.removeImageFromImagesCurrentlyUploading(image)
+                self.addImageToImagesThatFailedToUpload(image)
+                
+                NSNotificationCenter.defaultCenter().postNotificationName(BluemixDataManagerNotification.ImageUploadFailure.rawValue, object: nil)
+                
+            }
+                //success
+            else {
+                
+                self.addImageToImageTakenDuringAppSessionByIdDictionary(image)
+                self.removeImageFromImagesCurrentlyUploading(image)
+                
+                NSNotificationCenter.defaultCenter().postNotificationName(BluemixDataManagerNotification.ImageUploadSuccess.rawValue, object: nil)
+                
+            }
+        })
+        
+    }
+
+
+    func retryUploadingImagesThatFailedToUpload(){
+        
+        for image in imagesThatFailuredToUpload {
+            removeImageFromImagesThatFailedToUpload(image)
+            postNewImage(image)
+   
+        }
+ 
+    }
+    
+    func cancelUploadingImagesThatFailedToUpload(){
+        
+        for image in imagesThatFailuredToUpload {
+            removeImageFromImagesThatFailedToUpload(image) 
+        }
+        
+    }
+ 
+    
+    private func addImageToImagesThatFailedToUpload(image : Image){
+        
+        imagesThatFailuredToUpload.append(image)
+        
+    }
+    
+    private func removeImageFromImagesThatFailedToUpload(image : Image){
+        
+        imagesThatFailuredToUpload = imagesThatFailuredToUpload.filter({ $0 !== image})
+        
+    }
+    
+    private func addImageToImagesCurrentlyUploading(image : Image){
+        
+        imagesCurrentlyUploading.append(image)
+        
+    }
+    
+
+    private func removeImageFromImagesCurrentlyUploading(image: Image){
+        
+        imagesCurrentlyUploading = imagesCurrentlyUploading.filter({ $0 !== image})
+        
+    }
+    
+    
+    private func uploadImagesIfThereAreAnyLeftInTheQueue(){
+        
+        if(imagesCurrentlyUploading.count > 0){
+            postNewImage(imagesCurrentlyUploading[0])
+        }
+    }
+    
+    /**
+     Method adds the photo to the picturesTakenDuringAppSessionById cache to display the photo in the image feed while we wait for the photo to upload to.
+     */
+    private func addImageToImageTakenDuringAppSessionByIdDictionary(image : Image){
+        
+        if let userID = CurrentUser.facebookUserId {
+
+            let id = image.fileName + userID
+            imagesTakenDuringAppSessionById[id] = image.image
+        }
+    }
+    
+}
+
+// MARK: - Methods related to tags
+extension BluemixDataManager {
+    
+    /**
+     Method gets the most popular tags of BluePic. When tags receieved, it sends out the PopularTagsReceieved BluemixDataManagerNotification to the app
+     */
     func getPopularTags() {
         
         let requestURL = getBluemixBaseRequestURL() + "/" + kTagsEndPoint



enum BlueMixDataManagerError: ErrorType {
    case DocDoesNotExist
    case UserDoesNotExist
    case ConnectionFailure
}

enum BluemixDataManagerNotification : String {
    case GetAllImagesStarted = "GetAllImagesStarted"
    case ImagesRefreshed = "ImagesRefreshed"
    case ImageUploadBegan = "ImageUploadBegan"
    case ImageUploadSuccess = "ImageUploadSuccess"
    case ImageUploadFailure = "ImageUploadFailure"
    case PopularTagsReceived = "PopularTagsReceived"
}


class BluemixDataManager: NSObject {
    
    static let SharedInstance: BluemixDataManager = {
        
        var manager = BluemixDataManager()

    private let kUsersEndPoint = "users"
    private let kTagsEndPoint = "tags"
    
    //used to help the feed view model decide to show the loading animaiton on the feed vc
    var hasReceievedInitialImages = false
    
    /**
     Method initilizes the BMSClient
     */
    func initilizeBluemixAppRoute(){
        
        BMSClient.sharedInstance
            .initializeWithBluemixAppRoute(bluemixConfig.appRoute,
                                           bluemixAppGUID: bluemixConfig.appGUID,
                                           bluemixRegion: bluemixConfig.appRegion)
    }
    
    /**
     Method gets the Bluemix base request URL depending on if the isLocal key is set in the plist or not
     
     - returns: String
     */
    func getBluemixBaseRequestURL() -> String {
        
        if bluemixConfig.isLocal {
