 
 class PhotoAlbumViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate/*, NSFetchedResultsControllerDelegate*/ {
 
+    let BASE_URL = "https://api.flickr.com/services/rest/"
+    let METHOD_NAME = "flickr.photos.search"
+    let API_KEY = "fd2dca183606947b2f6c7ef036ae4e32"
+    let EXTRAS = "url_m"
+    let SAFE_SEARCH = "1"
+    let DATA_FORMAT = "json"
+    let NO_JSON_CALLBACK = "1"
+    let BOUNDING_BOX_HALF_WIDTH = 1.0
+    let BOUNDING_BOX_HALF_HEIGHT = 1.0
+    let LAT_MIN = -90.0
+    let LAT_MAX = 90.0
+    let LON_MIN = -180.0
+    let LON_MAX = 180.0
+    
     /* the map at the top of the view */
     @IBOutlet weak var mapView: MKMapView!
     

    var deletedIndexPaths: [NSIndexPath]!
    var updatedIndexPaths: [NSIndexPath]!
    
    
    override func viewDidLoad() {
        super.viewDidLoad()

            cell.imageView.alpha = 1.0
        }
    }
    
    
     func searchPhotosByLatLon() {
        
//        if !self.latitudeTextField.text.isEmpty && !self.longitudeTextField.text.isEmpty {
            if validLatitude(pin?.coordinate.latitude) && validLongitude(pin?.coordinate.longitude) {
                //self.photoTitleLabel.text = "Searching..."
                let methodArguments = [
                    "method": METHOD_NAME,
                    "api_key": API_KEY,
                    "bbox": createBoundingBoxString(),
                    "safe_search": SAFE_SEARCH,
                    "extras": EXTRAS,
                    "format": DATA_FORMAT,
                    "nojsoncallback": NO_JSON_CALLBACK
                ]
                getImageFromFlickrBySearch(methodArguments)
            } else {
                println("invalid latitude or longitude")
//                if !validLatitude(self.pin?.coordinate.latitude) && !validLongitude(self.pin?.coordinate.longitude) {
//                    self.photoTitleLabel.text = "Lat/Lon Invalid.\nLat should be [-90, 90].\nLon should be [-180, 180]."
//                } else if !validLatitude(self.pin?.coordinate.latitude) {
//                    self.photoTitleLabel.text = "Lat Invalid.\nLat should be [-90, 90]."
//                } else {
//                    self.photoTitleLabel.text = "Lon Invalid.\nLon should be [-180, 180]."
//                }
            }
//        } else {
//            if self.latitudeTextField.text.isEmpty && self.longitudeTextField.text.isEmpty {
//                self.photoTitleLabel.text = "Lat/Lon Empty."
//            } else if self.latitudeTextField.text.isEmpty {
//                self.photoTitleLabel.text = "Lat Empty."
//            } else {
//                self.photoTitleLabel.text = "Lon Empty."
//            }
//        }
    }
    
    
    /* Function makes first request to get a random page, then it makes a request to get an image with the random page */
    func getImageFromFlickrBySearch(methodArguments: [String : AnyObject]) {
        
        let session = NSURLSession.sharedSession()
        let urlString = BASE_URL + escapedParameters(methodArguments)
        let url = NSURL(string: urlString)!
        let request = NSURLRequest(URL: url)
        
        let task = session.dataTaskWithRequest(request) {data, response, downloadError in
            if let error = downloadError {
                println("Could not complete the request \(error)")
            } else {
                
                var parsingError: NSError? = nil
                let parsedResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments, error: &parsingError) as! NSDictionary
                
                if let photosDictionary = parsedResult.valueForKey("photos") as? [String:AnyObject] {
                    
                    if let totalPages = photosDictionary["pages"] as? Int {
                        
                        /* Flickr API - will only return up the 4000 images (100 per page * 40 page max) */
                        let pageLimit = min(totalPages, 40)
                        let randomPage = Int(arc4random_uniform(UInt32(pageLimit))) + 1
                        self.getImageFromFlickrBySearchWithPage(methodArguments, pageNumber: randomPage)
                        
                    } else {
                        println("Cant find key 'pages' in \(photosDictionary)")
                    }
                } else {
                    println("Cant find key 'photos' in \(parsedResult)")
                }
            }
        }
        
        task.resume()
    }
    
    func getImageFromFlickrBySearchWithPage(methodArguments: [String : AnyObject], pageNumber: Int) {
        
        /* Add the page to the method's arguments */
        var withPageDictionary = methodArguments
        withPageDictionary["page"] = pageNumber
        
        let session = NSURLSession.sharedSession()
        let urlString = BASE_URL + escapedParameters(withPageDictionary)
        let url = NSURL(string: urlString)!
        let request = NSURLRequest(URL: url)
        
        let task = session.dataTaskWithRequest(request) {data, response, downloadError in
            if let error = downloadError {
                println("Could not complete the request \(error)")
            } else {
                var parsingError: NSError? = nil
                let parsedResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments, error: &parsingError) as! NSDictionary
                
                if let photosDictionary = parsedResult.valueForKey("photos") as? [String:AnyObject] {
                    
                    var totalPhotosVal = 0
                    if let totalPhotos = photosDictionary["total"] as? String {
                        totalPhotosVal = (totalPhotos as NSString).integerValue
                    }
                    
                    if totalPhotosVal > 0 {
                        if let photosArray = photosDictionary["photo"] as? [[String: AnyObject]] {
                            
                            let randomPhotoIndex = Int(arc4random_uniform(UInt32(photosArray.count)))
                            let photoDictionary = photosArray[randomPhotoIndex] as [String: AnyObject]
                            
                            let photoTitle = photoDictionary["title"] as? String
                            let imageUrlString = photoDictionary["url_m"] as? String
                            let imageURL = NSURL(string: imageUrlString!)
                            
                            if let imageData = NSData(contentsOfURL: imageURL!) {
                                dispatch_async(dispatch_get_main_queue(), {
                                    //self.defaultLabel.alpha = 0.0
                                    self.flickrImage = UIImage(data: imageData)
                                    
                                    // force the cells to update now that the image has been downloaded
                                    dispatch_async(dispatch_get_main_queue()) {
                                        self.collectionView.reloadData()
                                    }
                                    
//                                    if methodArguments["bbox"] != nil {
//                                        self.photoTitleLabel.text = "\(self.getLatLonString()) \(photoTitle!)"
//                                    } else {
//                                        self.photoTitleLabel.text = "\(photoTitle!)"
//                                    }
                                    
                                })
                            } else {
                                println("Image does not exist at \(imageURL)")
                            }
                        } else {
                            println("Cant find key 'photo' in \(photosDictionary)")
                        }
                    } else {
                        dispatch_async(dispatch_get_main_queue(), { //TODO - what is with the comma?
                            println("No Photos Found.")
                            // TODO: Display a text string that indicates no images found.
//                            self.photoTitleLabel.text = "No Photos Found. Search Again."
//                            self.defaultLabel.alpha = 1.0
                            self.flickrImage = nil
                        })
                    }
                } else {
                    println("Cant find key 'photos' in \(parsedResult)")
                }
            }
        }
        
        task.resume()
    }

    /* Helper function: Given a dictionary of parameters, convert to a string for a url */
    func escapedParameters(parameters: [String : AnyObject]) -> String {
        
        var urlVars = [String]()
        
        for (key, value) in parameters {
            
            /* Make sure that it is a string value */
            let stringValue = "\(value)"
            
            /* Escape it */
            let escapedValue = stringValue.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())
            
            /* Append it */
            urlVars += [key + "=" + "\(escapedValue!)"]
            
        }
        
        return (!urlVars.isEmpty ? "?" : "") + join("&", urlVars)
    }

    /* Check to make sure the latitude falls within [-90, 90] */
    func validLatitude(lat: Double?) -> Bool {
        if let latitude : Double? = lat {
            if latitude < LAT_MIN || latitude > LAT_MAX {
                return false
            }
        } else {
            return false
        }
        return true
    }
    
    /* Check to make sure the longitude falls within [-180, 180] */
    func validLongitude(lon: Double?) -> Bool {
        if let longitude : Double? = lon {
            if longitude < LON_MIN || longitude > LON_MAX {
                return false
            }
        } else {
            return false
        }
        return true
    }
    
    func createBoundingBoxString() -> String {
        
        let latitude = pin?.coordinate.latitude
        let longitude = pin?.coordinate.longitude
        
        /* Fix added to ensure box is bounded by minimum and maximums */
        let bottom_left_lon = max(longitude! - BOUNDING_BOX_HALF_WIDTH, LON_MIN)
        let bottom_left_lat = max(latitude! - BOUNDING_BOX_HALF_HEIGHT, LAT_MIN)
        let top_right_lon = min(longitude! + BOUNDING_BOX_HALF_HEIGHT, LON_MAX)
        let top_right_lat = min(latitude! + BOUNDING_BOX_HALF_HEIGHT, LAT_MAX)
        
        return "\(bottom_left_lon),\(bottom_left_lat),\(top_right_lon),\(top_right_lat)"
    }
}

extension String {
    func toDouble() -> Double? {
        return NSNumberFormatter().numberFromString(self)?.doubleValue
    }
}
