             locationManager.stopMonitoringForRegion(region)
         }
     }
+    
+    func removeAllGeoNotificationsListeners() {
+        for object in locationManager.monitoredRegions {
+            let region = object as CLRegion
+            log("Stoping monitoring region \(region.identifier)")
+            locationManager.stopMonitoringForRegion(region)
+        }
+    }
+    
+    func monitorBest20(distances:[Double:Int]) {
+        // add monitor for first 20 sortedBy distance
+        if let allRegions = store.getAll() {
+            var i = 0
+            for (k,v) in Array(distances).sorted({$0.0 < $1.0}) {
+                if i < 20 {
+                    addOrUpdateGeoNotification(allRegions[v])
+                }
+                i++
+                println("\(k):\(v)")
+            }
+        }
+        log("monitoring best 20")
+        println("total monitored regions:\(locationManager.monitoredRegions.count)")
+    }
+    
+    func getDistancesArray(coordinate: CLLocationCoordinate2D) -> [Double:Int] {
+        var distances = [Double:Int]()
+
+        if let allRegions = store.getAll() {
+            for (index,region) in enumerate(allRegions) {
+                let lat = region["latitude"].asDouble!
+                let lng = region["longitude"].asDouble!
+                let radius = region["radius"].asDouble!
+                let distance = haversine(coordinate.latitude, lon1: coordinate.longitude, lat2: lat, lon2: lng, radius: radius)
+                distances[distance] = index
+                //log("distance:\(distance)")
+            }
+        }
+        return distances
+    }
 
     func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
-        log("update location")
+        log("update location called")
+        // select best 20 here
+        let monitoredRegions = locationManager.monitoredRegions
+        println("total monitored regions:\(monitoredRegions.count)")
+        // remove all notification first
+        removeAllGeoNotificationsListeners()
+        var locationArray = locations as Array
+        var locationObj = locationArray.last as CLLocation
+        var coord = locationObj.coordinate
+        // calculate distance
+        var distances = getDistancesArray(coord)
+        monitorBest20(distances)
     }
 
     func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) {

        super.init()
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        if (!CLLocationManager.locationServicesEnabled()) {
            log("Location services is not enabled")
        } else {

            return results
        }
    }
    
    func getTotalGeoNotifications() -> Int {
        let (resultSet, err) = SD.executeQuery("SELECT * FROM GeoNotifications")
        return resultSet.count
    }

    func remove(id: String) {
        let err = SD.executeChange("DELETE FROM GeoNotifications WHERE Id = ?", withArgs: [id])
