private void UpdateWeatherFromTable(Location pos, double radius, TimeSpan delta)
        {
            if (!tableinitialized)
            {
                var connectionString = ConfigurationManager.AppSettings["Microsoft.Storage.ConnectionString"];
                if (string.IsNullOrEmpty(connectionString))
                {
                    Console.WriteLine("Did not find table storage connection string in appsettings (app.config)");
                    return;
                }

                CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connectionString);
                // Create service client for credentialed access to the Table service.
                tableClient = new CloudTableClient(storageAccount.TableEndpoint, storageAccount.Credentials);
                table = tableClient.GetTableReference("airtable");
                tableinitialized = true; 
            }
            List<string> results = new List<string>();
            DateTime now = DateTime.Now;
            DateTime since = now.Subtract(delta);
            DateTimeOffset dto = since;

            string partitionFilter = TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, "airtelemetry");
            string sinceFilter = TableQuery.GenerateFilterConditionForDate("dto", QueryComparisons.GreaterThan, since); 

            string finalFilter = TableQuery.CombineFilters(partitionFilter, TableOperators.And, sinceFilter);

            TableQuery<AirTelemetry> query = new TableQuery<AirTelemetry>().Where(finalFilter);

            /* clearly not the most efficient way to do this but ok for a POC */ 
            foreach(AirTelemetry atrec in table.ExecuteQuery(query))
            {
                Console.WriteLine(atrec.airline +" " + atrec.flight);
                if(Haversine.InRange(pos, atrec.lat,atrec.lng, radius))
                {
                    if(atrec.lightning>20.0)
                    {
                        WeatherEvent we = new WeatherEvent(WeatherEventTypes.TSTORM, atrec.dto, new Location(atrec.lat, atrec.lng));
                        weatherevents.Add(we);
                    }
                    if (atrec.ice == 5.0)
                    {
                        WeatherEvent we = new WeatherEvent(WeatherEventTypes.LIGHT_ICE, atrec.dto, new Location(atrec.lat, atrec.lng));
                        weatherevents.Add(we);
                    }
                    if (atrec.ice == 10.0)
                    {
                        WeatherEvent we = new WeatherEvent(WeatherEventTypes.MODERATE_ICE, atrec.dto, new Location(atrec.lat, atrec.lng));
                        weatherevents.Add(we);
                    }
                    if (atrec.ice > 10.0)
                    {
                        WeatherEvent we = new WeatherEvent(WeatherEventTypes.HEAVY_ICE, atrec.dto, new Location(atrec.lat, atrec.lng));
                        weatherevents.Add(we);
                    }
                    if(atrec.windspeed==20.0 )
                    {
                        WeatherEvent we = new WeatherEvent(WeatherEventTypes.MODERATE_TURB, atrec.dto, new Location(atrec.lat, atrec.lng));
                        weatherevents.Add(we);
                    }
                    if (atrec.windspeed > 20.0)
                    {
                        WeatherEvent we = new WeatherEvent(WeatherEventTypes.HEAVY_TURB, atrec.dto, new Location(atrec.lat, atrec.lng));
                        weatherevents.Add(we);
                    }
                    if(atrec.windshear>=15.0 && atrec.windshear<=25.0)
                    {
                        WeatherEvent we = new WeatherEvent(WeatherEventTypes.MODERATE_SHEAR, atrec.dto, new Location(atrec.lat, atrec.lng));
                        weatherevents.Add(we);
                    }
                    if (atrec.windshear > 20.0)
                    {
                        WeatherEvent we = new WeatherEvent(WeatherEventTypes.HEAVY_SHEAR, atrec.Timestamp, new Location(atrec.lat, atrec.lng));
                        weatherevents.Add(we);
                    }
                }
            }

            return; 
        }
        async Task TrackFlight(AirTelemetry AT, Location origin, Location destination, double miles)
        {
            string json="";
            var eventHubConnectionString = GetEventHubConnectionString();
            var eventHubClient = EventHubClient.CreateFromConnectionString(eventHubConnectionString, eventHubName);
            int runningMileCount = 0;
            int updateWeatherInverval = 200;
            int updateWeatherRadius = 300; 

            /* how many miles we go per tick */
            int mileageIncrement = 30;

            Pushpin pin = new Pushpin();
            Label infoLabel = new Label(); 
            MapLayer InfoLayer = new MapLayer();

            AT.RowKey += DateTime.Now.ToShortDateString();
            /* get rid of illegal characters in row key */
            AT.RowKey = Regex.Replace(AT.RowKey, @"[\ /?#]", "");

            MapPolyline polyline = new MapPolyline();
            polyline.Stroke = new System.Windows.Media.SolidColorBrush(System.Windows.Media.Colors.Blue);
            polyline.StrokeThickness = 5;
            polyline.Opacity = 0.7;

            /* pre-plot the course so that we can draw the flight path on the map. we recalculate the bearing every
             * 100 miles (could/should be configurable) to get a true Great Circle route. */
            Location prev = origin;
            Location nxtl;
            double hdg = AT.heading; 
            polyline.Locations=new LocationCollection();
            polyline.Locations.Add(origin); 
            int j;
            for (j = 2; ;j++ )
            {
                nxtl = Haversine.PositionDistanceFromOrigin(prev, mileageIncrement / 0.00062137, hdg); 
                polyline.Locations.Add(nxtl);
                hdg = Haversine.Bearing(nxtl, destination);
                prev = nxtl;
                if (Haversine.InRange(nxtl, destination.Latitude, destination.Longitude, 100))
                {
                    polyline.Locations.Add(destination);
                    break;
                }

            }
            string rkey = AT.RowKey;
            AT.lat = origin.Latitude;
            AT.lng = origin.Longitude;
            UpdateMap(AT, pin, polyline, InfoLayer);
            UpdateWeatherFromTable(origin, 300, new TimeSpan(3, 0, 0));

            int i; 

            for (i = 0; i <= polyline.Locations.Count; i++)
            {
                await Task.Delay(2000);
                try
                {
                    AT.RowKey = rkey +'-'+ i.ToString();          /* row key must be unique or will overwrite existing */ 
                    FlightMap.Children.Clear();
                    FlightMap.Children.Add(polyline);

                    InfoLayer.Children.Clear();
                    /* we have two time stamps. the first is inherited from TableEntity and normally should not be used by applications. We
                     * initialize it here because Stream Analytics will barf on an illegal data (dates must be greater than 
                     * 12:00 midnight, January 1, 1601 A.D. (C.E.), UTC.). We do not use the inherited time stamp after this; this is what
                     * AT.dto is for */ 
                    AT.Timestamp = DateTime.Now;
                    AT.dto = DateTimeOffset.Now; 
                    AT.inflight = "true";
                    /* send distance in meters */
                    Location p = Haversine.PositionDistanceFromOrigin(new Location(AT.lat, AT.lng), mileageIncrement / 0.00062137, AT.heading); 
                    AT.lat = p.Latitude;
                    AT.lng = p.Longitude;

                    double b2 = Haversine.Bearing(p, destination);
                    AT.heading = b2; 

                    /* altitude in meters */
                    if (i < 5)
                        AT.altitude = 10000 / (6 - (i + 1)); /* ascending */
                    else if ((polyline.Locations.Count - i) < 5)
                        AT.altitude = 10000 / (polyline.Locations.Count+1 - i); /* descending */
                    else
                        AT.altitude = 10000;

                    /* initialize the data structure */ 
                    AT.ice = 0.0;
                    AT.windspeed = 0.0;
                    AT.windshear = 0.0;
                    AT.lightning = 0.0; 

                    /* encode weather conditions */
                    if(ltice)
                    {
                        AT.ice = 5.0;
                        WeatherEvent we = new WeatherEvent(WeatherEventTypes.LIGHT_ICE, DateTime.Now, p);
                        weatherevents.Add(we); 
                        ltice = false;
                    }
                    else if(mdice)
                    {
                        AT.ice = 10.0;
                        WeatherEvent we = new WeatherEvent(WeatherEventTypes.MODERATE_ICE, DateTime.Now, p);
                        weatherevents.Add(we); 
                        mdice = false; 
                    }
                    else if (hvice)
                    {
                        AT.ice = 20.0;
                        WeatherEvent we = new WeatherEvent(WeatherEventTypes.HEAVY_ICE, DateTime.Now, p);
                        weatherevents.Add(we); 
                        hvice = false; 
                    }
                    if(mdtub)
                    {
                        AT.windspeed = 20.0;
                        WeatherEvent we = new WeatherEvent(WeatherEventTypes.MODERATE_TURB, DateTime.Now, p);
                        weatherevents.Add(we); 
                        mdtub = false;
                    }
                    else if(hvtub)
                    {
                        AT.windspeed = 40.0;
                        WeatherEvent we = new WeatherEvent(WeatherEventTypes.HEAVY_TURB, DateTime.Now, p);
                        weatherevents.Add(we); 
                        hvtub = false; 
                    }
                    if(mdshr)
                    {
                        AT.windshear = 20.0;
                        WeatherEvent we = new WeatherEvent(WeatherEventTypes.MODERATE_SHEAR, DateTime.Now, p);
                        weatherevents.Add(we); 
                        mdshr = false;
                    }
                    else if(hvshr)
                    {
                        AT.windshear = 40.0;
                        WeatherEvent we = new WeatherEvent(WeatherEventTypes.HEAVY_SHEAR, DateTime.Now, p);
                        weatherevents.Add(we); 
                        hvshr = false; 
                    }
                    if(tstrm)
                    {
                        AT.lightning = 50.0;
                        WeatherEvent we = new WeatherEvent(WeatherEventTypes.TSTORM, DateTime.Now, p);
                        weatherevents.Add(we); 
                        tstrm = false; 
                    }

                    json = Newtonsoft.Json.JsonConvert.SerializeObject(AT);
                    Console.WriteLine("{0} > Sending message: {1}", DateTime.Now.ToString(), json);

                    FlightMap.Center.Latitude = p.Latitude;
                    FlightMap.Center.Longitude = p.Longitude;
                    FlightMap.Center.Altitude = AT.altitude; 
                    Location center = FlightMap.Center;
                    double zoom = FlightMap.ZoomLevel; 
                    FlightMap.SetView(center, zoom);

                    pin.Location = center;
                    FlightMap.Children.Add(pin);

                    infoLabel.Content = AT.airline + " " + AT.flight;
                    InfoLayer.AddChild(infoLabel, center);
                    WeatherImageLayer(InfoLayer);
                    FlightMap.Children.Add(InfoLayer);

                    UpdateFlightInfoBox(AT, false); 

                    if(Haversine.InRange(new Location(AT.lat, AT.lng), destination.Latitude,destination.Longitude,50))
                        break; 

                    await eventHubClient.SendAsync(new EventData(Encoding.UTF8.GetBytes(json)));
                    runningMileCount += mileageIncrement;
                    if(runningMileCount>=updateWeatherInverval)
                    {
                        runningMileCount = 0;
                        weatherevents.Clear(); 
                        UpdateWeatherFromTable(new Location(AT.lat, AT.lng), updateWeatherRadius, new TimeSpan(3, 0, 0));
                    }
                }
                catch (Exception exception)
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine("{0} > Exception: {1}", DateTime.Now.ToString(), exception.Message);
                    Console.ResetColor();
                }


            }
            AT.arrival = DateTime.Now;
            AT.inflight = "false";

            /* fudge the destination position */

            AT.lat=FlightMap.Center.Latitude = destination.Latitude;
            AT.lng=FlightMap.Center.Longitude = destination.Longitude;
            FlightMap.Center.Altitude = AT.altitude;

            UpdateMap(AT, pin, polyline, InfoLayer); 
 
            json = Newtonsoft.Json.JsonConvert.SerializeObject(AT);
            await eventHubClient.SendAsync(new EventData(Encoding.UTF8.GetBytes(json)));
            UpdateFlightInfoBox(AT, true);
            
        }