/// <summary>
        /// A sniffer entry (sniffer-mac, client-mac, rssi, and time) is added to currently built measurements.
        /// The procedures is the same for online and offline measurements - the only difference is that we do not track changes to
        /// online measurements as we are not interested in saving them persistently (at least not at the present time)
        /// </summary>
        /// <param name="snifferMac">The sniffer's mac address</param>
        /// <param name="clientMac">The client's mac adress</param>
        /// <param name="rssi">The client's rssi as measured by the sniffer</param>
        /// <param name="mode">'Offline' or 'Online' to help distinguish whether we want to save the data persistently</param>
        /// <param name="time">The time the sniffer entry was made. </param>
        private static void addToMeasurement(string snifferMac, string clientMac, int rssi, DateTime time)
        {
            Mode mode;

            //First, determine the mode.
            if (currentOfflineMeasurements.ContainsKey(clientMac))
            {
                mode = Mode.Offline;
            }
            else if (currentOnlineMeasurements.ContainsKey(clientMac))
            {
                mode = Mode.Online;
            }
            else
            {
                return; //Unknown client mac
            }
            ConcurrentDictionary <string, SnifferWifiMeasurement> dic = getMeasurementDictionary(mode);

            SnifferWifiMeasurement curWifiMeasurement = dic[clientMac];

            //Update end meas time (even more may come..)
            curWifiMeasurement.meas_time_end = time;

            //Add or update histogram with snifferMac, rssi value
            SnifferHistogram curHist = curWifiMeasurement.SnifferHistograms.FirstOrDefault(h => h.Mac == snifferMac && h.value == rssi);

            if (curHist == null) //insert new histogram
            {
                curHist       = new SnifferHistogram();
                curHist.Mac   = snifferMac;
                curHist.value = rssi;
                curHist.count = 0;
                curWifiMeasurement.SnifferHistograms.Add(curHist);
                curHist.SnifferWifiMeasurement = curWifiMeasurement;

                if (mode == Mode.Offline)
                {
                    context.AddRelatedObject(curWifiMeasurement, "SnifferHistograms", curHist);
                }
            }
            curHist.count++; //yet another count for this rssi value

            //In the offline mode we actually save the data.
            if (mode == Mode.Offline)
            {
                context.UpdateObject(curWifiMeasurement);
                context.UpdateObject(curHist);
            }
        }
        //Upload a symbolicLocation in the background (update or create)
        //Form: AsyncTask<[Input Parameter Type], [Progress Report Type], [Result Type]>
        private void UploadSymbolicLocationTask(SymbolicLocation tmpSymLoc)
        {
            isUploading = true;
            mContext    = LocationService.radiomapContext;

            Vertex           currentVertex = Map2DOffline.SelectedOfflineVertex;
            SymbolicLocation currentSymLoc = currentVertex.SymbolicLocations.FirstOrDefault();

            //1) upload NEW symbolic location
            if (currentSymLoc == null)
            {
                mContext.AddRelatedObject(currentVertex, "SymbolicLocations", tmpSymLoc);
                currentVertex.SymbolicLocations.Add(tmpSymLoc);
            }
            //2) or UPDATE existing
            else
            {
                //copy updated values
                currentSymLoc.title       = tmpSymLoc.title;
                currentSymLoc.description = tmpSymLoc.description;
                currentSymLoc.url         = tmpSymLoc.url;
                currentSymLoc.is_entrance = tmpSymLoc.is_entrance;

                mContext.UpdateObject(currentSymLoc);
            }
            try
            {
                mContext.BeginSaveChanges(OnChangesSaved, mContext);

                //uploadProgressBar.Visibility = System.Windows.Visibility.Visible;
                uploadProgressIndicator.IsVisible = isUploading;
            }
            catch (Exception ex)
            {
                isUploading = false;
                uploadProgressIndicator.IsVisible = isUploading;

                MessageBox.Show(string.Format("The changes could not be saved.\n"
                                              + "The following error occurred: {0}", ex.Message));
            }
        }
        public int SaveMeasurement(string clientMac)
        {
            const int error  = -1;
            int       result = error; //change if success

            if (clientMac == null)
            {
                return(error);
            }

            if (!(savedMeasuringClients.ContainsKey(clientMac) && savedOfflineMeasurements.ContainsKey(clientMac)))
            {
                return(error);
            }

            //Remove the measurement from from the 'current' list.
            SnifferWifiMeasurement curWifi = savedOfflineMeasurements[clientMac];
            Vertex curVertex = savedMeasuringClients[clientMac];

            savedOfflineMeasurements.Remove(clientMac);
            savedMeasuringClients.Remove(clientMac);

            Building curBuilding = LoadedBuildings.First(b => b.ID == curVertex.Building_ID);

            //save changes persistently
            try
            {
                //Notify context about changes
                radiomapEntities localContext = new radiomapEntities(radiomapUri);
                if (curVertex.ID <= UNBOUND_ID_STARTVALUE) //unbound location
                {
                    AbsoluteLocation absLoc = curVertex.AbsoluteLocations.First();
                    localContext.AttachTo("Buildings", curBuilding);
                    localContext.AddRelatedObject(curBuilding, "Vertices", curVertex);
                    localContext.AddRelatedObject(curVertex, "AbsoluteLocations", absLoc);
                }
                else
                {
                    localContext.AttachTo("Vertices", curVertex);
                    result = curVertex.ID;
                }
                localContext.AddRelatedObject(curVertex, "SnifferWifiMeasurements", curWifi);
                foreach (SnifferHistogram curHist in curWifi.SnifferHistograms)
                {
                    localContext.AddRelatedObject(curWifi, "SnifferHistograms", curHist);
                }

                //save to database
                DataServiceResponse response = localContext.SaveChanges(SaveChangesOptions.Batch);

                // Enumerate the returned responses. If a new vertex, add it to the current building and return its id.
                foreach (ChangeOperationResponse change in response)
                {
                    // Get the descriptor for the entity.
                    EntityDescriptor descriptor = change.Descriptor as EntityDescriptor;

                    if (descriptor != null)
                    {
                        if (descriptor.Entity is SnifferWifiMeasurement)
                        {
                            //Yes, the measurement got saved
                            Console.WriteLine("Measurement saved."); //dummy statement
                        }
                        else if (descriptor.Entity is Vertex)
                        {
                            Vertex newVertex = descriptor.Entity as Vertex;
                            curBuilding.Vertices.Add(newVertex);
                            result = newVertex.ID;
                        }
                    }
                }

                return(result);
            }
            catch (DataServiceRequestException)
            {
                return(error);
            }
        }