private static void OnPositionEstimatesSaved(IAsyncResult result)
        {
            bool errorOccured = false;

            radiomapEntities context = result.AsyncState as radiomapEntities;

            try
            {
                // Complete the save changes operation and display the response.
                DataServiceResponse response = context.EndSaveChanges(result);

                foreach (ChangeOperationResponse changeResponse in response)
                {
                    if (changeResponse.Error != null)
                    {
                        errorOccured = true;
                    }
                }
                if (!errorOccured)
                {
                    //Maybe raise success event?
                }
            }
            catch (Exception ex)
            {
                Exception exCopy = ex;
            }
        }
        private void RemoveEdgeTask()
        {
            if (CurrentEdge == null)
            {
                throw new InvalidOperationException("No link to remove");
            }

            isUploading = true;
            mContext    = LocationService.radiomapContext;

            //Add the edge
            mContext.DeleteObject(CurrentEdge);

            try
            {
                mContext.BeginSaveChanges(OnChangesSaved, mContext);

                uploadProgressIndicator.IsVisible = isUploading;
            }
            catch (Exception ex)
            {
                isUploading = false;
                uploadProgressIndicator.IsVisible = isUploading;

                // Display the error from the response.
                string errorMsg = ex.InnerException != null ?
                                  ex.InnerException.Message :
                                  ex.Message;
                MessageBox.Show(string.Format("The following error occured: {0}", errorMsg));
            }
        }
        private static void UploadTrackingDataAndFlushBuffer()
        {
            if (bufferedTrackedPositions == null)
            {
                return;
            }
            if (bufferedTrackedPositions.Count == 0)
            {
                return;
            }

            //copy tracking data and clear buffer
            TrackedPosition[] tmp;
            lock (bufferedTrackedPositionsLock)
            {
                int numPositions = bufferedTrackedPositions.Count;
                tmp = new TrackedPosition[numPositions];
                bufferedTrackedPositions.CopyTo(tmp);
                bufferedTrackedPositions.Clear();
            }

            radiomapEntities context = new radiomapEntities(radiomapUri);

            foreach (TrackedPosition pos in tmp)
            {
                context.AddToTrackedPositions(pos);
            }
            context.BeginSaveChanges(SaveChangesOptions.Batch, OnPositionEstimatesSaved, context);
        }
        private void OnChangesSaved(IAsyncResult result)
        {
            bool errorOccured = false;

            // Use the Dispatcher to ensure that the
            // asynchronous call returns in the correct thread.
            Dispatcher.BeginInvoke(() =>
            {
                isUploading = false;
                uploadProgressIndicator.IsVisible = isUploading;

                mContext = result.AsyncState as radiomapEntities;
                try
                {
                    // Complete the save changes operation and display the response.
                    DataServiceResponse response = mContext.EndSaveChanges(result);

                    foreach (ChangeOperationResponse changeResponse in response)
                    {
                        if (changeResponse.Error != null) errorOccured = true;
                    }
                    if (!errorOccured)
                    {
                        Globals.ShowDialog(this, Globals.CHANGES_SAVED, Globals.DURATION_SHORT);

                        //Finalize edge, i.e., add it to the endpoint's edges and to the building
                        /*
                        Building b = LocationService.CurrentBuilding;
                        b.Edges.Add(mCurrentEdge);
                        foreach (Vertex v in mCurrentEdge.Vertices)
                        {
                            if (!v.Edges.Contains(mCurrentEdge))
                                v.Edges.Add(mCurrentEdge);
                        }
                        */
                        NavigationService.GoBack();
                        //Tell everyone the good news!
                        if (OnEdgeAdded != null)
                        {
                            OnEdgeAdded(this, EventArgs.Empty);
                        }
                    }
                    else
                    {
                        MessageBox.Show("An error occured. One or more changes could not be saved.");
                    }
                }
                catch (Exception ex)
                {
                    // Display the error from the response.
                    string errorMsg = ex.InnerException != null ?
                        ex.InnerException.Message :
                        ex.Message;
                    MessageBox.Show(string.Format("The following error occured: {0}", errorMsg));
                }
            }
            );
        }
        /// <summary>
        /// Downloads a radio map for the building with the specified id.
        /// </summary>
        /// <param name="buildingId"></param>
        public static void DownloadRadioMap(int buildingId)
        {
            radiomapContext = new radiomapEntities(radiomapUri);
            buildings       = new DataServiceCollection <Building>(radiomapContext);

            String expandOptions = "Building_Floors,Vertices,Vertices/AbsoluteLocations,Vertices/SymbolicLocations,Vertices/Edges,Edges,Edges/Vertices,Edges/Vertices/AbsoluteLocations";
            var    query         = from b in radiomapContext.Buildings.Expand(expandOptions)
                                   where b.ID == buildingId
                                   select b;

            // Register for the LoadCompleted event.
            buildings.LoadCompleted
                += new EventHandler <LoadCompletedEventArgs>(buildings_LoadCompleted);
            buildings.LoadAsync(query);
        }
        private void OnChangesSaved(IAsyncResult result)
        {
            bool errorOccured = false;

            // Use the Dispatcher to ensure that the
            // asynchronous call returns in the correct thread.
            Dispatcher.BeginInvoke(() =>
            {
                isUploading = false;
                uploadProgressIndicator.IsVisible = isUploading;

                mContext = result.AsyncState as radiomapEntities;
                try
                {
                    // Complete the save changes operation and display the response.
                    DataServiceResponse response = mContext.EndSaveChanges(result);

                    foreach (ChangeOperationResponse changeResponse in response)
                    {
                        if (changeResponse.Error != null)
                        {
                            errorOccured = true;
                        }
                    }
                    if (!errorOccured)
                    {
                        Globals.ShowDialog(this, Globals.CHANGES_SAVED, Globals.DURATION_SHORT);
                        NavigationService.GoBack();
                        if (OnSymbolicLocationChange != null)
                        {
                            OnSymbolicLocationChange(this, null);
                        }
                    }
                    else
                    {
                        MessageBox.Show("An error occured. One or more changes could not be saved.");
                    }
                }
                catch (Exception ex)
                {
                    // Display the error from the response.
                    MessageBox.Show(string.Format("The following error occured: {0}", ex.Message));
                }
            }
                                   );
        }
        //UDP udgaven:

        /*
         * private static void StartTcpServer()
         * {
         *  LoadRadioMap();
         *
         *  //Start listening for sniffer measurements
         *  UdpClient udpc = new UdpClient(5555);
         *  Console.WriteLine("Server started, servicing on port 2055");
         *  IPEndPoint ep = null;
         *  while (true)
         *  {
         *      byte[] rawData = udpc.Receive(ref ep);
         *      string strData = Encoding.ASCII.GetString(rawData);
         *      string[] msgParts = strData.Split(' ');
         *
         *      try
         *      {
         *          string snifferMac = msgParts[0];
         *          string hms = msgParts[1]; //e.g.: 10:01:21.185194
         *          DateTime time = getTime(hms);
         *          string strRssi = msgParts[2];
         *          int rssi = int.Parse(strRssi);
         *          string clientMac = msgParts[3];
         *
         *          if (isCurrentlyMeasuring(clientMac))
         *          {
         *              addToMeasurement(snifferMac, clientMac, rssi, time);
         *          }
         *          Console.WriteLine("Sniffer mac = {0}; time = {1}; RSSI = {2}; clientMac = {3}", snifferMac, time, strRssi, clientMac);
         *      }
         *      catch (Exception ex)
         *      {
         *          Console.WriteLine(ex.Message);
         *      }
         *  }
         * }
         */

        private static void LoadRadioMap()
        {
            if (!IsDownloadingRadioMap)
            {
                IsDownloadingRadioMap = true;

                context = new radiomapEntities(radiomapUri);
                //Load LoadedBuildings
                String expandOptions = "Building_MacInfos,Building_Floors,Edges,Vertices,Vertices/AbsoluteLocations,Vertices/SymbolicLocations,Vertices/SnifferWifiMeasurements,Vertices/SnifferWifiMeasurements/SnifferHistograms";
                DataServiceQuery <Building> query = context.Buildings.Expand(expandOptions);

                //NOTE: Maybe surround with try-catch and try again
                LoadedBuildings = query.Execute().ToList();

                IsDownloadingRadioMap = false;
                checkBuildings();
            }
        }
        //Upload a symbolicLocation in the background (update or create)
        //Form: AsyncTask<[Input Parameter Type], [Progress Report Type], [Result Type]>
        private void AddEdgeTask()
        {
            isUploading = true;
            mContext = LocationService.radiomapContext;

            /*
            Uri radiomapUri = new Uri("http://smartcampusaau.cs.aau.dk/RadioMapService3/RadioMapService.svc/");
            mContext = new radiomapEntities(radiomapUri);
            Building b = (mContext.Buildings.Where(b1 => b1.ID == LocationService.CurrentBuilding.ID)).First();
            Vertex v0 = (mContext.Vertices.Where(v => v.ID == mCurrentEdge.Vertices[0].ID)).First();
            Vertex v1 = (mContext.Vertices.Where(v => v.ID == mCurrentEdge.Vertices[1].ID)).Single();
            mContext.AddToEdges(mCurrentEdge);
            mContext.AddLink(b, "Edges", mCurrentEdge);
            mContext.AddLink(v0, "Edges", mCurrentEdge);
            mContext.AddLink(v1, "Edges", mCurrentEdge);
            */

            //Link to/from the building and endpoints
            mContext.AddToEdges(mCurrentEdge);
            Building b = LocationService.CurrentBuilding;
            b.Edges.Add(mCurrentEdge);
            /*
            foreach (Vertex v in mCurrentEdge.Vertices)
            {
                if (!v.Edges.Contains(mCurrentEdge))
                    v.Edges.Add(mCurrentEdge);
            }
            */
            try
            {
                mContext.BeginSaveChanges(OnChangesSaved, mContext);

                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));
            }
        }
        //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);
            }
        }