WeatherInformation WP8: MapPage improvements
[CSharpForFun/.git] / WindowsPhone / WP8 / WeatherInformation / WeatherInformation / MainPage.xaml.cs
1 using Microsoft.Phone.Controls;
2 using System;
3 using System.Linq;
4 using System.Globalization;
5 using System.Windows;
6 using System.Windows.Controls;
7 using System.Windows.Navigation;
8 using WeatherInformation.Model;
9 using WeatherInformation.Model.Services;
10 using WeatherInformation.Resources;
11 using WeatherInformation.ViewModels;
12 using System.Threading.Tasks;
13 using WeatherInformation.Model.JsonDataParser;
14 using Microsoft.Phone.Shell;
15
16 namespace WeatherInformation
17 {
18     public partial class MainPage : PhoneApplicationPage
19     {
20         private MainViewModel _mainViewModel;
21         private bool _isNewPageInstance = false;
22
23         // Constructor
24         public MainPage()
25         {
26             InitializeComponent();
27
28             _isNewPageInstance = true;
29
30             // Código de ejemplo para traducir ApplicationBar
31             //BuildLocalizedApplicationBar();
32         }
33
34
35         // Cargar datos para los elementos MainViewModel
36         protected override void OnNavigatedTo(NavigationEventArgs e)
37         {
38             base.OnNavigatedTo(e);
39
40             CreateFlipTile();
41
42             // If _isNewPageInstance is true, the page constuctor has been called, so
43             // state may need to be restored.
44             if (_isNewPageInstance)
45             {
46                 if (_mainViewModel == null)
47                 {
48                     _mainViewModel = new MainViewModel(new SettingsViewModel());
49                 }
50
51                 DataContext = _mainViewModel;
52             }
53             // Set _isNewPageInstance to false. If the user navigates back to this page
54             // and it has remained in memory, this value will continue to be false.
55             _isNewPageInstance = false;
56
57             UpdateApplicationDataUI();
58         }
59
60         async private void UpdateApplicationDataUI()
61         {
62             Location locationItem = null;
63             using (var db = new LocationDataContext(LocationDataContext.DBConnectionString))
64             {
65                 locationItem = db.Locations.Where(location => location.IsSelected).FirstOrDefault();
66             }
67
68             if (locationItem == null)
69             {
70                 // Nothing to do.
71                 return;
72             }
73
74             // If the application member variable is not empty,
75             // set the page's data object from the application member variable.
76             WeatherData weatherData = (Application.Current as WeatherInformation.App).ApplicationDataObject;
77             if (!IsDataFresh(locationItem.LastRemoteDataUpdate) || weatherData == null)
78             {
79                 // Load remote data (aynchronous way by means of async/await)
80
81                 // Gets the data from the web.
82                 (Application.Current as WeatherInformation.App).ApplicationDataObject =
83                     await GetRemoteDataAsync(locationItem);
84
85                 using (var db = new LocationDataContext(LocationDataContext.DBConnectionString))
86                 {
87                     locationItem = db.Locations.Where(location => location.IsSelected).FirstOrDefault();
88                     locationItem.LastRemoteDataUpdate = DateTime.UtcNow;
89                     db.SubmitChanges();
90                 }
91             }
92
93             // Call UpdateUI on the UI thread.
94             // Without ConfigureAwait(false) await returns data on the calling thread. In this case the calling one
95             // is the UI thread. So, I can save the call to Dispatcher.BeginInvoke.
96             //Dispatcher.BeginInvoke(() => UpdateUI());
97             UpdateUI();
98         }
99
100         void UpdateUI()
101         {
102             // Set the ApplicationData and ApplicationDataStatus members of the ViewModel
103             WeatherData weatherData = (Application.Current as WeatherInformation.App).ApplicationDataObject;
104
105             if (weatherData != null)
106             {
107                 _mainViewModel.LoadData(weatherData);
108             }
109         }
110
111         private void LongListSelector_SelectionChanged(object sender, SelectionChangedEventArgs e)
112         {
113             LongListSelector longListSelector = sender as LongListSelector;
114
115             // TODO: with LINQ :(
116             ItemViewModel element = longListSelector.SelectedItem as ItemViewModel;
117             int index = longListSelector.ItemsSource.IndexOf(element);
118             String uri = string.Format(CultureInfo.InvariantCulture, "/SelectedDatePage.xaml?parameter={0}", index);
119             NavigationService.Navigate(new Uri(uri, UriKind.Relative));
120         }
121
122         /// <summary>
123         /// Retrieve remote weather data.
124         /// </summary>
125         async public Task<WeatherData> GetRemoteDataAsync(Location locationItem)
126         {
127             double latitude = locationItem.Latitude;
128             double longitude = locationItem.Longitude;
129             int resultsNumber = Convert.ToInt32(AppResources.APIOpenWeatherMapResultsNumber);
130
131             CustomHTTPClient httpClient = new CustomHTTPClient();
132
133             string formattedForecastURL = String.Format(
134                 CultureInfo.InvariantCulture, AppResources.URIAPIOpenWeatherMapForecast,
135                 AppResources.APIVersionOpenWeatherMap, latitude, longitude, resultsNumber);
136             string jsonForecast = await httpClient.GetWeatherDataAsync(formattedForecastURL).ConfigureAwait(false);
137
138             string formattedCurrentURL = String.Format(
139                 CultureInfo.InvariantCulture, AppResources.URIAPIOpenWeatherMapCurrent,
140                 AppResources.APIVersionOpenWeatherMap, latitude, longitude, resultsNumber);
141             string jsonCurrent = await httpClient.GetWeatherDataAsync(formattedCurrentURL).ConfigureAwait(false);
142
143             var parser = new ServiceParser(new JsonParser());
144             var weatherData = parser.WeatherDataParser(jsonForecast, jsonCurrent, locationItem.City, locationItem.Country);
145
146             return weatherData;
147         }
148
149         private bool IsDataFresh(DateTime? lastUpdate)
150         {
151             if (lastUpdate == null)
152             {
153                 return false;
154             }
155
156             // Check the time elapsed since data was last saved to isolated storage.
157             TimeSpan TimeSinceLastSave = DateTime.UtcNow - lastUpdate.Value;
158
159             if (TimeSinceLastSave.TotalSeconds < 30)
160             {
161                 return true;
162             }
163
164             return false;
165         }
166
167         private void Location_Click(object sender, EventArgs e)
168         {
169             NavigationService.Navigate(new Uri("/MapPage.xaml", UriKind.Relative));
170         }
171
172         private void Settings_Click(object sender, EventArgs e)
173         {
174             NavigationService.Navigate(new Uri("/SettingsPage.xaml", UriKind.Relative));
175         }
176
177         private void CreateFlipTile()
178         {
179             ShellTile tile = ShellTile.ActiveTiles.FirstOrDefault(
180                 x => x.NavigationUri.ToString().Contains("flip"));
181             tile = ShellTile.ActiveTiles.First();
182             var activeTiles = ShellTile.ActiveTiles;
183
184             var tileData = new FlipTileData();
185             tileData.Title = "GUSTAVO RULES";
186             tileData.BackTitle = "Gustavo Rules Back";
187             tileData.BackContent = "Gustavo Back Content";
188             tileData.WideBackContent = "Gustavo Wid Back Content";
189             tile.Update(tileData);
190
191         }
192
193         // Código de ejemplo para compilar una ApplicationBar traducida
194         //private void BuildLocalizedApplicationBar()
195         //{
196         //    // Establecer ApplicationBar de la página en una nueva instancia de ApplicationBar.
197         //    ApplicationBar = new ApplicationBar();
198
199         //    // Crear un nuevo botón y establecer el valor de texto en la cadena traducida de AppResources.
200         //    ApplicationBarIconButton appBarButton = new ApplicationBarIconButton(new Uri("/Assets/AppBar/appbar.add.rest.png", UriKind.Relative));
201         //    appBarButton.Text = AppResources.AppBarButtonText;
202         //    ApplicationBar.Buttons.Add(appBarButton);
203
204         //    // Crear un nuevo elemento de menú con la cadena traducida de AppResources.
205         //    ApplicationBarMenuItem appBarMenuItem = new ApplicationBarMenuItem(AppResources.AppBarMenuItemText);
206         //    ApplicationBar.MenuItems.Add(appBarMenuItem);
207         //}
208     }
209 }