using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.IO; using System.IO.IsolatedStorage; using System.Linq; using System.ServiceModel; using System.Threading; using System.Windows; using MahTweets.Mobile.Core; using MahTweets.Mobile.Core.Filters; using MahTweets.Mobile.Core.Interfaces; using MahTweets.Mobile.Core.Repositories; using MahTweets.Mobile.Core.Services; //using MahTweets.Mobile.TumblrPlugin.Models; using MahTweets.Mobile.mtpush; using MahTweets.Mobile.TwitterPlugin.Models; using MahTweets.Mobile.Views; //using MahTweets.Mobile.YammerPlugin.Models; using Microsoft.Phone.Controls; using Microsoft.Phone.Notification; namespace MahTweets.Mobile.ViewModels { public class MainViewModel : MahViewModelBase, IDisposable { public static HttpNotificationChannel Channel; //private const string ChannelName = "mahtweets"; //private const string PushAddress = "http://192.168.0.19:8732/Design_Time_Addresses/SiteStreamingNotifications/Service1/"; //private const string PushAddress = "http://services.mahtweets.com:8000/push/"; private Timer _refreshTimer; private readonly INavigationService _navigationService; private readonly ContactRepository _contactRepository; private readonly Func _streamViewModelFactory; private readonly Func _microBlogFactory; private readonly Func _stalkerFactory; private readonly IApplicationSettings _applicationSettings; private AccountRepository _accounts; private StalkerRepository _stalkers; private string _prevSharedPhotoId = ""; private IStatusUpdatesManager StatusManager { get; set; } public AvailableMicroblogs AvailableConnections { get; set; } public AvailableStalkers AvailableStalkers { get; set; } public FilterRepository Filters { get; set; } private SearchRepository _searchRepository { get; set; } private ObservableCollection _pivotItems = new ObservableCollection(); public ObservableCollection PivotItems { get { return _pivotItems; } set { _pivotItems = value; RaisePropertyChanged(() => PivotItems); } } public ObservableCollection Streams { get; set; } public ObservableCollection Searches { get; set; } public MainViewModel( INavigationService navigationService, AccountRepository accounts, StalkerRepository stalkerRepository, ContactRepository contactRepository, IStatusUpdatesManager statusUpdatesManager, FilterRepository filterRepository, SearchRepository searchRepository, AvailableMicroblogs availableMicroblogs, AvailableStalkers availableStalkers, IEnumerable registeredBlogs, IEnumerable registeredStalkers, IApplicationSettings applicationSettings, Func streamViewModelFactory, Func microBlogFactory, Func stalkerFactory ) { _navigationService = navigationService; _contactRepository = contactRepository; _applicationSettings = applicationSettings; _streamViewModelFactory = streamViewModelFactory; _microBlogFactory = microBlogFactory; _stalkerFactory = stalkerFactory; Streams = new ObservableCollection(); Searches = new ObservableCollection(); Accounts = accounts; Stalkers = stalkerRepository; Filters = filterRepository; _searchRepository = searchRepository; StatusManager = statusUpdatesManager; AvailableConnections = availableMicroblogs; AvailableStalkers = availableStalkers; foreach (var registeredBlog in registeredBlogs) { if (!AvailableConnections.Contains(registeredBlog)) AvailableConnections.Add(registeredBlog); } foreach (var registeredStalker in registeredStalkers) { if (!AvailableStalkers.Contains(registeredStalker)) AvailableStalkers.Add(registeredStalker); } Startup(); } public void Startup() { AddExistingAccounts(); _refreshTimer = new Timer(o => Refresh(false), null, 0, 180000); SetupFeatures(); } public void StopTimer() { _refreshTimer.Dispose(); } public void RestartTimer() { _refreshTimer = new Timer(o => Refresh(false), null, 0, 180000); } private void SetupFeatures() { //Setup filters if (Filters.Count > 0) return; List filters = Settings.GetFilters().ToList(); foreach (var f in filters) { foreach (var inner in f.Filters.OfType()) { var x = inner; var microblog = Accounts.Where(a => a.Credentials.AccountName == x.MicroblogAccountName && a.Protocol == x.MicroblogName).FirstOrDefault(); if (microblog != null) x.Microblog = microblog; //MahTweets.Mobile.Core.MentionUpdate x.UpdateType = GetUpdateType(x.UpdateTypeName); } Filters.Add(f); } List searches = Settings.GetSavedSearches().ToList(); foreach (var s in searches) { _searchRepository.Add(s); } } public UpdateType GetUpdateType(String name) { //MahTweets.Mobile.Core.MentionUpdate return (from u in App.UpdateTypes where u.GetType().AssemblyQualifiedName == name select (UpdateType)Activator.CreateInstance(u.GetType())).FirstOrDefault(); } private void AddExistingAccounts() { var accounts = Settings.GetCredentials().ToList(); try { foreach (var account in accounts) { var account1 = account; var b = (from mb in AvailableConnections where mb.Protocol.Equals(account1.Protocol) select mb).FirstOrDefault(); if (b != null) { CreateAndAddAccount(b, account, false); continue; } var s = (from stalker in AvailableStalkers where stalker.Protocol.Equals(account1.Protocol) select stalker).FirstOrDefault(); if (s != null) { CreateAndAddAccount(s, account); continue; } } } catch (NullReferenceException) { //this occurs on the first run of the app, need to dig into Phone.Data.Entity } catch (InvalidOperationException ex) { if (ex.Message == "Sequence contains no elements") { } } } public void Refresh(bool force) { DateTime? lastRefresh = null; if (IsolatedStorageSettings.ApplicationSettings.Contains("LastRefreshTime")) lastRefresh = _applicationSettings.LastRefreshTime; if (force || lastRefresh == null || DateTime.Now.Subtract((DateTime)lastRefresh).TotalMinutes > 3) { foreach (var connection in Accounts) { var microblog = connection; if (!microblog.IsRefreshing) AddWork(() => microblog.Refresh(force)); } foreach (var s in Searches) AddWork(() => s.Search(s.Term, false)); PerformWork(); _applicationSettings.LastRefreshTime = DateTime.Now; } } public void CreateAndAddAccount(IMicroblog baseAccount, Credential credentials, bool isNewAccount) { var newAccount = _microBlogFactory(baseAccount.GetType()); newAccount.Credentials = credentials; newAccount.Connect(); if (isNewAccount) newAccount.Refresh(true); Accounts.Add(newAccount); } public void CreateAndAddAccount(IKnowWhereYouAre baseAccount, Credential credentials) { var newAccount = _stalkerFactory(baseAccount.GetType()); newAccount.Credentials = credentials; newAccount.Connect(); Stalkers.Add(newAccount); } public AccountRepository Accounts { get { return _accounts; } set { _accounts = value; RaisePropertyChanged(() => Accounts); } } public StalkerRepository Stalkers { get { return _stalkers; } set { _stalkers = value; RaisePropertyChanged(() => Stalkers); } } public void LoadInitialStreams() { if (Streams == null) Streams = new ObservableCollection(); PivotItems = new ObservableCollection(); RaisePropertyChanged(() => PivotItems); if (PivotItems.Count > 0) return; GlobalDispatcher.Dispatcher.BeginInvoke( () => { if (Accounts.Count > 0) { //Load up the streams if (Filters.Count > 0) SetupExistingFilters(); else NoFiltersPrompt(); } }); } private void NoFiltersPrompt() { MessageBoxResult result = MessageBox.Show( "Oops! Looks like you've got no columns, would you like the defaults setup?", "No filters!", MessageBoxButton.OKCancel); if (result == MessageBoxResult.OK) { StreamModel defaultEverything = StreamModel.CreateDefault(); var defaultResponses = new StreamModel { GroupName = "@me", Filters = new ObservableCollection { new UpdateTypeFilter(FilterBehaviour.Include,Accounts[0],new MentionUpdate()), new UpdateTypeFilter(FilterBehaviour.Include,Accounts[0],new DirectMessageUpdate()) } }; Filters.Add(defaultResponses); Filters.Add(defaultEverything); Settings.StoreStream(defaultResponses); Settings.StoreStream(defaultEverything); RaisePropertyChanged(() => Filters); RaisePropertyChanged(() => Streams); LoadInitialStreams(); //_navigationService.Navigate(new Uri("/Views/MainView.xaml?" + DateTime.Now, UriKind.RelativeOrAbsolute)); } } private void SetupExistingFilters() { foreach (var filter in Filters) { StreamViewModel svm = Streams.Where(s => s.Filters != null && s.Filters.GroupName == filter.GroupName).FirstOrDefault(); if (svm == null) { svm = _streamViewModelFactory(); svm.Filters = new StreamModel { Filters = filter.Filters, GroupName = filter.GroupName }; } if (!Streams.Contains(svm)) Streams.Add(svm); try { var sv = new StreamView { DataContext = svm }; var pi = new PivotItem { Header = svm.Filters.GroupName, Content = sv, HorizontalContentAlignment = HorizontalAlignment.Stretch }; PivotItems.Add(pi); RaisePropertyChanged(() => PivotItems); RaisePropertyChanged(() => Streams); } catch (Exception ex) { //TODO: Logging Debug.WriteLine(ex); } } foreach (var s in _searchRepository) { var svm = new SearchViewModel(_accounts, _contactRepository, _searchRepository) { Term = s.Term }; Searches.Add(svm); var sv = new SearchStreamView { DataContext = svm }; var pi = new PivotItem { Header = s.Term, Content = sv, HorizontalContentAlignment = HorizontalAlignment.Stretch }; PivotItems.Add(pi); RaisePropertyChanged(() => PivotItems); } } public void EditColumn(PivotItem pi) { if (pi == null) return; if (pi.Content is StreamView) ((StreamView)pi.Content).BeginEdit(); if (pi.Content is SearchStreamView) ((SearchStreamView)pi.Content).BeginEdit(); } public StreamView GetColumn(PivotItem pi) { if (pi != null && pi.Content is StreamView) { return ((StreamView)pi.Content); } return null; } public void GotoSettings() { _navigationService.Navigate(new Uri("/Views/SettingsView.xaml", UriKind.RelativeOrAbsolute)); } public void ShowComposition() { _navigationService.Navigate(new Uri("/Views/CompositionView.xaml", UriKind.RelativeOrAbsolute)); } public void SharePhoto(string fileId) { if (!_prevSharedPhotoId.Equals(fileId)) { _navigationService.Navigate(new Uri("/Views/CompositionView.xaml?FileId=" + fileId, UriKind.RelativeOrAbsolute)); _prevSharedPhotoId = fileId; } } internal void GoToNewColumn() { _navigationService.Navigate(new Uri("/Views/AddColumnView.xaml", UriKind.RelativeOrAbsolute)); } public new void Dispose() { _refreshTimer.Dispose(); base.Dispose(); } public void GoToSearch() { _navigationService.Navigate(new Uri("/Views/SearchView.xaml", UriKind.RelativeOrAbsolute)); } public void LoadTimeline() { //return; var knownStatusTypes = new List { typeof (Tweet), typeof (SelfDirectMessage), typeof (DirectMessage), //typeof (YammerUpdate), //typeof (TumblrUpdate) }; using (var store = IsolatedStorageFile.GetUserStoreForApplication()) { foreach (var t in knownStatusTypes) { var path = t.FullName + ".dat"; try { if (store.FileExists(path)) { using (var s = store.OpenFile(path, FileMode.Open)) using (var reader = new BinaryReader(s)) { var itemCount = reader.ReadInt32(); var updates = new List(); for (var i = 0; i < itemCount; i++) { var update = (IStatusUpdate)Activator.CreateInstance(t); update.Load("", reader, _contactRepository, Accounts); updates.Add(update); } StatusManager.Send(updates); } } } catch (Exception) { //TODO: Logging store.DeleteFile(path); } } } } public void SaveTimeline() { var x = StatusManager.Collection.GroupBy(t => t.GetType()); foreach (var y in x) { using (var store = IsolatedStorageFile.GetUserStoreForApplication()) { try { var path = y.Key.FullName + ".dat"; using (Stream s = store.OpenFile(path, FileMode.Create, FileAccess.Write)) { var writer = new BinaryWriter(s); writer.Write(y.Count()); foreach (var i in y.OrderByDescending(t => t.Time).Take(50)) { i.Save(writer); } writer.Flush(); } } catch (IsolatedStorageException ex) { Debug.WriteLine(ex); } } } } /* #region Notification stuff public void HandleNotifications() { if (!Accounts.Any()) return; if (String.IsNullOrEmpty(_applicationSettings.PushAccount)) return; var id = Accounts.Where(a => a.Protocol == "twitter" && a.Credentials.AccountId == _applicationSettings.PushAccount).First().Credentials.AccountId; if (id == null) return; try { Channel = HttpNotificationChannel.Find(ChannelName); if (Channel != null) { Debug.WriteLine(Channel.ChannelUri.ToString()); if (!Channel.IsShellTileBound) Channel.BindToShellTile(); if (!Channel.IsShellToastBound) Channel.BindToShellToast(); SetNotifications(id); } else { Channel = new HttpNotificationChannel(ChannelName); Channel.ChannelUriUpdated += (updatedSender, updatedArgs) => { Debug.WriteLine(Channel.ChannelUri.ToString()); SetNotifications(id); }; Channel.ErrorOccurred += (errorSender, errorArgs) => { Debug.WriteLine(errorArgs.ErrorAdditionalData); SetNotifications(id); }; Channel.Open(); Channel.BindToShellTile(); Channel.BindToShellToast(); } } catch (Exception ex) { Console.Write(ex.Message); Debug.WriteLine(ex); } //}); } public void SetNotifications(String id) { Channel = HttpNotificationChannel.Find(ChannelName); if (Channel == null) { HandleNotifications(); return; } var option = _applicationSettings.Push; var c = new SiteStreamingServiceClient(new BasicHttpBinding(), new EndpointAddress(PushAddress)); c.RequestNotificationsCompleted += c_RequestNotificationsCompleted; c.StopNotificationsCompleted += c_StopNotificationsCompleted; c.OpenCompleted += (s, ie) => c.RequestNotificationsAsync(id, Channel.ChannelUri.ToString(), option); c.OpenAsync(); } void c_RequestNotificationsCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e) { } void c_StopNotificationsCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e) { } internal void RemoveNotifications(String Id) { if (Channel == null) { HandleNotifications(); return; } Channel = HttpNotificationChannel.Find(ChannelName); var c = new SiteStreamingServiceClient(new BasicHttpBinding(), new EndpointAddress(PushAddress)); c.OpenCompleted += (s, ie) => c.StopNotificationsAsync(Id, null); c.OpenAsync(); } #endregion */ } }