Statistics
| Branch: | Revision:

root / trunk / Pithos.Client.WPF / Shell / ShellViewModel.cs @ 422c9598

History | View | Annotate | Download (25.8 kB)

1 c53aa229 Panagiotis Kanavos
´╗┐using System.Collections.Concurrent;
2 c53aa229 Panagiotis Kanavos
using System.Diagnostics;
3 c28a075a Panagiotis Kanavos
using System.Diagnostics.Contracts;
4 c53aa229 Panagiotis Kanavos
using System.IO;
5 c28a075a Panagiotis Kanavos
using System.Net;
6 d17258c2 Panagiotis Kanavos
using System.Reflection;
7 c53aa229 Panagiotis Kanavos
using System.Runtime.InteropServices;
8 c53aa229 Panagiotis Kanavos
using System.ServiceModel;
9 c53aa229 Panagiotis Kanavos
using System.Threading.Tasks;
10 c53aa229 Panagiotis Kanavos
using System.Windows;
11 fb9d6e00 Panagiotis Kanavos
using System.Windows.Controls.Primitives;
12 9bae55d1 Panagiotis Kanavos
using Caliburn.Micro;
13 c53aa229 Panagiotis Kanavos
using Hardcodet.Wpf.TaskbarNotification;
14 c53aa229 Panagiotis Kanavos
using Pithos.Client.WPF.Configuration;
15 42800be8 Panagiotis Kanavos
using Pithos.Client.WPF.FileProperties;
16 65282d58 Panagiotis Kanavos
using Pithos.Client.WPF.Preferences;
17 d3a13891 Panagiotis Kanavos
using Pithos.Client.WPF.SelectiveSynch;
18 42800be8 Panagiotis Kanavos
using Pithos.Client.WPF.Services;
19 5cb9d74f Panagiotis Kanavos
using Pithos.Client.WPF.Shell;
20 c53aa229 Panagiotis Kanavos
using Pithos.Core;
21 29a6b387 Panagiotis Kanavos
using Pithos.Core.Agents;
22 c53aa229 Panagiotis Kanavos
using Pithos.Interfaces;
23 c53aa229 Panagiotis Kanavos
using System;
24 c53aa229 Panagiotis Kanavos
using System.Collections.Generic;
25 c53aa229 Panagiotis Kanavos
using System.Linq;
26 0bd56b7c Panagiotis Kanavos
using Pithos.Network;
27 c53aa229 Panagiotis Kanavos
using StatusService = Pithos.Client.WPF.Services.StatusService;
28 9bae55d1 Panagiotis Kanavos
29 9bae55d1 Panagiotis Kanavos
namespace Pithos.Client.WPF {
30 4ec636f6 Panagiotis Kanavos
	using System.ComponentModel.Composition;
31 9bae55d1 Panagiotis Kanavos
32 4ec636f6 Panagiotis Kanavos
	
33 cf761c0d Panagiotis Kanavos
	///<summary>
34 cf761c0d Panagiotis Kanavos
	/// The "shell" of the Pithos application displays the taskbar  icon, menu and notifications.
35 cf761c0d Panagiotis Kanavos
	/// The shell also hosts the status service called by shell extensions to retrieve file info
36 cf761c0d Panagiotis Kanavos
	///</summary>
37 cf761c0d Panagiotis Kanavos
	///<remarks>
38 cf761c0d Panagiotis Kanavos
	/// It is a strange "shell" as its main visible element is an icon instead of a window
39 cf761c0d Panagiotis Kanavos
	/// The shell subscribes to the following events:
40 cf761c0d Panagiotis Kanavos
	/// * Notification:  Raised by components that want to notify the user. Usually displayed in a balloon
41 cf761c0d Panagiotis Kanavos
	/// * SelectiveSynchChanges: Notifies that the user made changes to the selective synch folders for an account. Raised by the Selective Synch dialog. Located here because the monitors are here
42 cf761c0d Panagiotis Kanavos
	/// * ShowFilePropertiesEvent: Raised when a shell command requests the display of the file/container properties dialog
43 cf761c0d Panagiotis Kanavos
	///</remarks>		
44 cf761c0d Panagiotis Kanavos
	//TODO: CODE SMELL Why does the shell handle the SelectiveSynchChanges?
45 4ec636f6 Panagiotis Kanavos
	[Export(typeof(IShell))]
46 4ec636f6 Panagiotis Kanavos
	public class ShellViewModel : Screen, IStatusNotification, IShell,
47 4ec636f6 Panagiotis Kanavos
		IHandle<Notification>, IHandle<SelectiveSynchChanges>, IHandle<ShowFilePropertiesEvent>
48 4ec636f6 Panagiotis Kanavos
	{
49 cf761c0d Panagiotis Kanavos
		//The Status Checker provides the current synch state
50 cf761c0d Panagiotis Kanavos
		//TODO: Could we remove the status checker and use events in its place?
51 4f6d51d4 Panagiotis Kanavos
		private readonly IStatusChecker _statusChecker;
52 4f6d51d4 Panagiotis Kanavos
		private readonly IEventAggregator _events;
53 c53aa229 Panagiotis Kanavos
54 4ec636f6 Panagiotis Kanavos
		public PithosSettings Settings { get; private set; }
55 c53aa229 Panagiotis Kanavos
56 4ec636f6 Panagiotis Kanavos
57 4f6d51d4 Panagiotis Kanavos
        private readonly ConcurrentDictionary<string, PithosMonitor> _monitors = new ConcurrentDictionary<string, PithosMonitor>();
58 cf761c0d Panagiotis Kanavos
		///<summary>
59 cf761c0d Panagiotis Kanavos
		/// Dictionary of account monitors, keyed by account
60 cf761c0d Panagiotis Kanavos
		///</summary>
61 cf761c0d Panagiotis Kanavos
		///<remarks>
62 cf761c0d Panagiotis Kanavos
		/// One monitor class is created for each account. The Shell needs access to the monitors to execute start/stop/pause commands,
63 cf761c0d Panagiotis Kanavos
		/// retrieve account and boject info		
64 cf761c0d Panagiotis Kanavos
		///</remarks>
65 cf761c0d Panagiotis Kanavos
		// TODO: Does the Shell REALLY need access to the monitors? Could we achieve the same results with a better design?
66 cf761c0d Panagiotis Kanavos
		// TODO: The monitors should be internal to Pithos.Core, even though exposing them makes coding of the Object and Container windows easier
67 4ec636f6 Panagiotis Kanavos
        public ConcurrentDictionary<string, PithosMonitor> Monitors
68 4ec636f6 Panagiotis Kanavos
		{
69 4ec636f6 Panagiotis Kanavos
			get { return _monitors; }
70 4ec636f6 Panagiotis Kanavos
		}
71 c53aa229 Panagiotis Kanavos
72 cf761c0d Panagiotis Kanavos
73 4f6d51d4 Panagiotis Kanavos
	    ///<summary>
74 4f6d51d4 Panagiotis Kanavos
	    /// The status service is used by Shell extensions to retrieve file status information
75 4f6d51d4 Panagiotis Kanavos
	    ///</summary>
76 4f6d51d4 Panagiotis Kanavos
	    //TODO: CODE SMELL! This is the shell! While hosting in the shell makes executing start/stop commands easier, it is still a smell
77 4f6d51d4 Panagiotis Kanavos
	    private ServiceHost _statusService;
78 c53aa229 Panagiotis Kanavos
79 cf761c0d Panagiotis Kanavos
		//Logging in the Pithos client is provided by log4net
80 4ec636f6 Panagiotis Kanavos
		private static readonly log4net.ILog Log = log4net.LogManager.GetLogger("Pithos");
81 c53aa229 Panagiotis Kanavos
82 422c9598 Panagiotis Kanavos
        //Lazily initialized File Version info. This is done once and lazily to avoid blocking the UI
83 422c9598 Panagiotis Kanavos
        private Lazy<FileVersionInfo> _fileVersion;
84 422c9598 Panagiotis Kanavos
85 cf761c0d Panagiotis Kanavos
		///<summary>
86 cf761c0d Panagiotis Kanavos
		/// The Shell depends on MEF to provide implementations for windowManager, events, the status checker service and the settings
87 cf761c0d Panagiotis Kanavos
		///</summary>
88 cf761c0d Panagiotis Kanavos
		///<remarks>
89 cf761c0d Panagiotis Kanavos
		/// The PithosSettings class encapsulates the app's settings to abstract their storage mechanism (App settings, a database or registry)
90 cf761c0d Panagiotis Kanavos
		///</remarks>
91 4ec636f6 Panagiotis Kanavos
		[ImportingConstructor]		
92 4ec636f6 Panagiotis Kanavos
		public ShellViewModel(IWindowManager windowManager, IEventAggregator events, IStatusChecker statusChecker, PithosSettings settings)
93 4ec636f6 Panagiotis Kanavos
		{
94 4ec636f6 Panagiotis Kanavos
			try
95 4ec636f6 Panagiotis Kanavos
			{
96 d3a13891 Panagiotis Kanavos
97 4ec636f6 Panagiotis Kanavos
				_windowManager = windowManager;
98 cf761c0d Panagiotis Kanavos
				//CHECK: Caliburn doesn't need explicit command construction
99 4ec636f6 Panagiotis Kanavos
				//OpenPithosFolderCommand = new PithosCommand(OpenPithosFolder);
100 4ec636f6 Panagiotis Kanavos
				_statusChecker = statusChecker;
101 cf761c0d Panagiotis Kanavos
				//The event subst
102 4ec636f6 Panagiotis Kanavos
				_events = events;
103 4ec636f6 Panagiotis Kanavos
				_events.Subscribe(this);
104 c53aa229 Panagiotis Kanavos
105 4ec636f6 Panagiotis Kanavos
				Settings = settings;
106 c53aa229 Panagiotis Kanavos
107 4ec636f6 Panagiotis Kanavos
				StatusMessage = "In Synch";
108 7e26c075 Panagiotis Kanavos
109 422c9598 Panagiotis Kanavos
                _fileVersion=  new Lazy<FileVersionInfo>(() =>
110 422c9598 Panagiotis Kanavos
                {
111 422c9598 Panagiotis Kanavos
                    Assembly assembly = Assembly.GetExecutingAssembly();
112 422c9598 Panagiotis Kanavos
                    var fileVersion = FileVersionInfo.GetVersionInfo(assembly.Location);
113 422c9598 Panagiotis Kanavos
                    return fileVersion;
114 422c9598 Panagiotis Kanavos
                });
115 4ec636f6 Panagiotis Kanavos
				_accounts.CollectionChanged += (sender, e) =>
116 4ec636f6 Panagiotis Kanavos
												   {
117 4ec636f6 Panagiotis Kanavos
													   NotifyOfPropertyChange(() => OpenFolderCaption);
118 4ec636f6 Panagiotis Kanavos
													   NotifyOfPropertyChange(() => HasAccounts);
119 4ec636f6 Panagiotis Kanavos
												   };
120 6aa29f4f Panagiotis Kanavos
121 4ec636f6 Panagiotis Kanavos
			}
122 4ec636f6 Panagiotis Kanavos
			catch (Exception exc)
123 4ec636f6 Panagiotis Kanavos
			{
124 4ec636f6 Panagiotis Kanavos
				Log.Error("Error while starting the ShellViewModel",exc);
125 4ec636f6 Panagiotis Kanavos
				throw;
126 4ec636f6 Panagiotis Kanavos
			}
127 4ec636f6 Panagiotis Kanavos
		}
128 c53aa229 Panagiotis Kanavos
129 6aa29f4f Panagiotis Kanavos
130 4ec636f6 Panagiotis Kanavos
		protected override void OnActivate()
131 4ec636f6 Panagiotis Kanavos
		{
132 4ec636f6 Panagiotis Kanavos
			base.OnActivate();
133 42800be8 Panagiotis Kanavos
134 4ec636f6 Panagiotis Kanavos
			StartMonitoring();                    
135 4ec636f6 Panagiotis Kanavos
		}
136 7b0a5fec Panagiotis Kanavos
137 42800be8 Panagiotis Kanavos
138 4f6d51d4 Panagiotis Kanavos
		private async void StartMonitoring()
139 4ec636f6 Panagiotis Kanavos
		{
140 4ec636f6 Panagiotis Kanavos
			try
141 4ec636f6 Panagiotis Kanavos
			{
142 4ec636f6 Panagiotis Kanavos
				var accounts = Settings.Accounts.Select(MonitorAccount);
143 4ec636f6 Panagiotis Kanavos
				await TaskEx.WhenAll(accounts);
144 4ec636f6 Panagiotis Kanavos
				_statusService = StatusService.Start();
145 692ec33b Panagiotis Kanavos
146 692ec33b Panagiotis Kanavos
/*
147 4ec636f6 Panagiotis Kanavos
				foreach (var account in Settings.Accounts)
148 4ec636f6 Panagiotis Kanavos
				{
149 4ec636f6 Panagiotis Kanavos
					await MonitorAccount(account);
150 4ec636f6 Panagiotis Kanavos
				}
151 692ec33b Panagiotis Kanavos
*/
152 4ec636f6 Panagiotis Kanavos
				
153 4ec636f6 Panagiotis Kanavos
			}
154 4ec636f6 Panagiotis Kanavos
			catch (AggregateException exc)
155 4ec636f6 Panagiotis Kanavos
			{
156 4ec636f6 Panagiotis Kanavos
				exc.Handle(e =>
157 4ec636f6 Panagiotis Kanavos
				{
158 4ec636f6 Panagiotis Kanavos
					Log.Error("Error while starting monitoring", e);
159 4ec636f6 Panagiotis Kanavos
					return true;
160 4ec636f6 Panagiotis Kanavos
				});
161 4ec636f6 Panagiotis Kanavos
				throw;
162 4ec636f6 Panagiotis Kanavos
			}
163 4ec636f6 Panagiotis Kanavos
		}
164 4ec636f6 Panagiotis Kanavos
165 4ec636f6 Panagiotis Kanavos
		protected override void OnDeactivate(bool close)
166 4ec636f6 Panagiotis Kanavos
		{
167 4ec636f6 Panagiotis Kanavos
			base.OnDeactivate(close);
168 4ec636f6 Panagiotis Kanavos
			if (close)
169 4ec636f6 Panagiotis Kanavos
			{
170 4ec636f6 Panagiotis Kanavos
				StatusService.Stop(_statusService);
171 4ec636f6 Panagiotis Kanavos
				_statusService = null;
172 4ec636f6 Panagiotis Kanavos
			}
173 4ec636f6 Panagiotis Kanavos
		}
174 4ec636f6 Panagiotis Kanavos
175 4ec636f6 Panagiotis Kanavos
		public Task MonitorAccount(AccountSettings account)
176 4ec636f6 Panagiotis Kanavos
		{
177 4ec636f6 Panagiotis Kanavos
			return Task.Factory.StartNew(() =>
178 4ec636f6 Panagiotis Kanavos
			{                                                
179 4f6d51d4 Panagiotis Kanavos
				PithosMonitor monitor;
180 4ec636f6 Panagiotis Kanavos
				var accountName = account.AccountName;
181 4ec636f6 Panagiotis Kanavos
182 4ec636f6 Panagiotis Kanavos
				if (_monitors.TryGetValue(accountName, out monitor))
183 4ec636f6 Panagiotis Kanavos
				{
184 4ec636f6 Panagiotis Kanavos
					//If the account is active
185 4ec636f6 Panagiotis Kanavos
					if (account.IsActive)
186 4ec636f6 Panagiotis Kanavos
						//Start the monitor. It's OK to start an already started monitor,
187 4ec636f6 Panagiotis Kanavos
						//it will just ignore the call                        
188 4ec636f6 Panagiotis Kanavos
						StartMonitor(monitor).Wait();                        
189 4ec636f6 Panagiotis Kanavos
					else
190 4ec636f6 Panagiotis Kanavos
					{
191 4ec636f6 Panagiotis Kanavos
						//If the account is inactive
192 4ec636f6 Panagiotis Kanavos
						//Stop and remove the monitor
193 4ec636f6 Panagiotis Kanavos
						RemoveMonitor(accountName);
194 4ec636f6 Panagiotis Kanavos
					}
195 4ec636f6 Panagiotis Kanavos
					return;
196 4ec636f6 Panagiotis Kanavos
				}
197 4ec636f6 Panagiotis Kanavos
198 70f12b36 Panagiotis Kanavos
                
199 4ec636f6 Panagiotis Kanavos
				//Create a new monitor/ Can't use MEF here, it would return a single instance for all monitors
200 4ec636f6 Panagiotis Kanavos
				monitor = new PithosMonitor
201 4ec636f6 Panagiotis Kanavos
							  {
202 4ec636f6 Panagiotis Kanavos
								  UserName = accountName,
203 4ec636f6 Panagiotis Kanavos
								  ApiKey = account.ApiKey,                                  
204 4ec636f6 Panagiotis Kanavos
								  StatusNotification = this,
205 4ec636f6 Panagiotis Kanavos
								  RootPath = account.RootPath
206 4ec636f6 Panagiotis Kanavos
							  };
207 4ec636f6 Panagiotis Kanavos
				//PithosMonitor uses MEF so we need to resolve it
208 4ec636f6 Panagiotis Kanavos
				IoC.BuildUp(monitor);
209 4ec636f6 Panagiotis Kanavos
210 4f6d51d4 Panagiotis Kanavos
			    monitor.AuthenticationUrl = account.ServerUrl;
211 4ec636f6 Panagiotis Kanavos
212 4ec636f6 Panagiotis Kanavos
				_monitors[accountName] = monitor;
213 4ec636f6 Panagiotis Kanavos
214 4ec636f6 Panagiotis Kanavos
				if (account.IsActive)
215 4ec636f6 Panagiotis Kanavos
				{
216 4ec636f6 Panagiotis Kanavos
					//Don't start a monitor if it doesn't have an account and ApiKey
217 4ec636f6 Panagiotis Kanavos
					if (String.IsNullOrWhiteSpace(monitor.UserName) ||
218 4ec636f6 Panagiotis Kanavos
						String.IsNullOrWhiteSpace(monitor.ApiKey))
219 4ec636f6 Panagiotis Kanavos
						return;
220 4ec636f6 Panagiotis Kanavos
					StartMonitor(monitor);
221 4ec636f6 Panagiotis Kanavos
				}
222 4ec636f6 Panagiotis Kanavos
			});
223 4ec636f6 Panagiotis Kanavos
		}
224 4ec636f6 Panagiotis Kanavos
225 4ec636f6 Panagiotis Kanavos
226 4ec636f6 Panagiotis Kanavos
		protected override void OnViewLoaded(object view)
227 4ec636f6 Panagiotis Kanavos
		{
228 4ec636f6 Panagiotis Kanavos
			UpdateStatus();
229 4ec636f6 Panagiotis Kanavos
			var window = (Window)view;            
230 4ec636f6 Panagiotis Kanavos
			TaskEx.Delay(1000).ContinueWith(t => Execute.OnUIThread(window.Hide));
231 4ec636f6 Panagiotis Kanavos
			base.OnViewLoaded(view);
232 4ec636f6 Panagiotis Kanavos
		}
233 4ec636f6 Panagiotis Kanavos
234 4ec636f6 Panagiotis Kanavos
235 4ec636f6 Panagiotis Kanavos
		#region Status Properties
236 4ec636f6 Panagiotis Kanavos
237 4ec636f6 Panagiotis Kanavos
		private string _statusMessage;
238 4ec636f6 Panagiotis Kanavos
		public string StatusMessage
239 4ec636f6 Panagiotis Kanavos
		{
240 4ec636f6 Panagiotis Kanavos
			get { return _statusMessage; }
241 4ec636f6 Panagiotis Kanavos
			set
242 4ec636f6 Panagiotis Kanavos
			{
243 4ec636f6 Panagiotis Kanavos
				_statusMessage = value;
244 4ec636f6 Panagiotis Kanavos
				NotifyOfPropertyChange(() => StatusMessage);
245 4ec636f6 Panagiotis Kanavos
			}
246 4ec636f6 Panagiotis Kanavos
		}
247 4ec636f6 Panagiotis Kanavos
248 4ec636f6 Panagiotis Kanavos
		private readonly ObservableConcurrentCollection<AccountInfo> _accounts = new ObservableConcurrentCollection<AccountInfo>();
249 4ec636f6 Panagiotis Kanavos
		public ObservableConcurrentCollection<AccountInfo> Accounts
250 4ec636f6 Panagiotis Kanavos
		{
251 4ec636f6 Panagiotis Kanavos
			get { return _accounts; }
252 4ec636f6 Panagiotis Kanavos
		}
253 4ec636f6 Panagiotis Kanavos
254 4ec636f6 Panagiotis Kanavos
		public bool HasAccounts
255 4ec636f6 Panagiotis Kanavos
		{
256 4ec636f6 Panagiotis Kanavos
			get { return _accounts.Count > 0; }
257 4ec636f6 Panagiotis Kanavos
		}
258 4ec636f6 Panagiotis Kanavos
259 4ec636f6 Panagiotis Kanavos
260 4ec636f6 Panagiotis Kanavos
		public string OpenFolderCaption
261 4ec636f6 Panagiotis Kanavos
		{
262 4ec636f6 Panagiotis Kanavos
			get
263 4ec636f6 Panagiotis Kanavos
			{
264 4ec636f6 Panagiotis Kanavos
				return (_accounts.Count == 0)
265 4ec636f6 Panagiotis Kanavos
						? "No Accounts Defined"
266 4ec636f6 Panagiotis Kanavos
						: "Open Pithos Folder";
267 4ec636f6 Panagiotis Kanavos
			}
268 4ec636f6 Panagiotis Kanavos
		}
269 4ec636f6 Panagiotis Kanavos
270 4ec636f6 Panagiotis Kanavos
		private string _pauseSyncCaption="Pause Synching";
271 4ec636f6 Panagiotis Kanavos
		public string PauseSyncCaption
272 4ec636f6 Panagiotis Kanavos
		{
273 4ec636f6 Panagiotis Kanavos
			get { return _pauseSyncCaption; }
274 4ec636f6 Panagiotis Kanavos
			set
275 4ec636f6 Panagiotis Kanavos
			{
276 4ec636f6 Panagiotis Kanavos
				_pauseSyncCaption = value;
277 4ec636f6 Panagiotis Kanavos
				NotifyOfPropertyChange(() => PauseSyncCaption);
278 4ec636f6 Panagiotis Kanavos
			}
279 4ec636f6 Panagiotis Kanavos
		}
280 4ec636f6 Panagiotis Kanavos
281 4ec636f6 Panagiotis Kanavos
		private readonly ObservableConcurrentCollection<FileEntry> _recentFiles = new ObservableConcurrentCollection<FileEntry>();
282 4ec636f6 Panagiotis Kanavos
		public ObservableConcurrentCollection<FileEntry> RecentFiles
283 4ec636f6 Panagiotis Kanavos
		{
284 4ec636f6 Panagiotis Kanavos
			get { return _recentFiles; }
285 4ec636f6 Panagiotis Kanavos
		}
286 4ec636f6 Panagiotis Kanavos
287 4ec636f6 Panagiotis Kanavos
288 4ec636f6 Panagiotis Kanavos
		private string _statusIcon="../Images/Pithos.ico";
289 4ec636f6 Panagiotis Kanavos
		public string StatusIcon
290 4ec636f6 Panagiotis Kanavos
		{
291 4ec636f6 Panagiotis Kanavos
			get { return _statusIcon; }
292 4ec636f6 Panagiotis Kanavos
			set
293 4ec636f6 Panagiotis Kanavos
			{
294 4f6d51d4 Panagiotis Kanavos
                //TODO: Ensure all status icons use the Pithos logo
295 4f6d51d4 Panagiotis Kanavos
				_statusIcon = value;
296 4ec636f6 Panagiotis Kanavos
				NotifyOfPropertyChange(() => StatusIcon);
297 4ec636f6 Panagiotis Kanavos
			}
298 4ec636f6 Panagiotis Kanavos
		}
299 4ec636f6 Panagiotis Kanavos
300 4ec636f6 Panagiotis Kanavos
		#endregion
301 4ec636f6 Panagiotis Kanavos
302 4ec636f6 Panagiotis Kanavos
		#region Commands
303 4ec636f6 Panagiotis Kanavos
304 4ec636f6 Panagiotis Kanavos
		public void ShowPreferences()
305 4ec636f6 Panagiotis Kanavos
		{
306 4ec636f6 Panagiotis Kanavos
			Settings.Reload();
307 4ec636f6 Panagiotis Kanavos
			var preferences = new PreferencesViewModel(_windowManager,_events, this,Settings);            
308 4ec636f6 Panagiotis Kanavos
			_windowManager.ShowDialog(preferences);
309 4ec636f6 Panagiotis Kanavos
			
310 4ec636f6 Panagiotis Kanavos
		}
311 4ec636f6 Panagiotis Kanavos
312 4ec636f6 Panagiotis Kanavos
		public void AboutPithos()
313 4ec636f6 Panagiotis Kanavos
		{
314 4ec636f6 Panagiotis Kanavos
			var about = new AboutViewModel();
315 4ec636f6 Panagiotis Kanavos
			_windowManager.ShowWindow(about);
316 4ec636f6 Panagiotis Kanavos
		}
317 4ec636f6 Panagiotis Kanavos
318 4ec636f6 Panagiotis Kanavos
		public void SendFeedback()
319 4ec636f6 Panagiotis Kanavos
		{
320 4ec636f6 Panagiotis Kanavos
			var feedBack =  IoC.Get<FeedbackViewModel>();
321 4ec636f6 Panagiotis Kanavos
			_windowManager.ShowWindow(feedBack);
322 4ec636f6 Panagiotis Kanavos
		}
323 4ec636f6 Panagiotis Kanavos
324 4ec636f6 Panagiotis Kanavos
		//public PithosCommand OpenPithosFolderCommand { get; private set; }
325 4ec636f6 Panagiotis Kanavos
326 4ec636f6 Panagiotis Kanavos
		public void OpenPithosFolder()
327 4ec636f6 Panagiotis Kanavos
		{
328 4ec636f6 Panagiotis Kanavos
			var account = Settings.Accounts.FirstOrDefault(acc => acc.IsActive);
329 4ec636f6 Panagiotis Kanavos
			if (account == null)
330 4ec636f6 Panagiotis Kanavos
				return;
331 4ec636f6 Panagiotis Kanavos
			Process.Start(account.RootPath);
332 4ec636f6 Panagiotis Kanavos
		}
333 4ec636f6 Panagiotis Kanavos
334 4ec636f6 Panagiotis Kanavos
		public void OpenPithosFolder(AccountInfo account)
335 4ec636f6 Panagiotis Kanavos
		{
336 4ec636f6 Panagiotis Kanavos
			Process.Start(account.AccountPath);
337 4ec636f6 Panagiotis Kanavos
		}
338 4ec636f6 Panagiotis Kanavos
339 4ec636f6 Panagiotis Kanavos
		
340 f734ab5b Panagiotis Kanavos
/*
341 4ec636f6 Panagiotis Kanavos
		public void GoToSite()
342 4ec636f6 Panagiotis Kanavos
		{            
343 4ec636f6 Panagiotis Kanavos
			var site = Properties.Settings.Default.PithosSite;
344 4ec636f6 Panagiotis Kanavos
			Process.Start(site);            
345 4ec636f6 Panagiotis Kanavos
		}
346 f734ab5b Panagiotis Kanavos
*/
347 6aa29f4f Panagiotis Kanavos
348 4ec636f6 Panagiotis Kanavos
		public void GoToSite(AccountInfo account)
349 4ec636f6 Panagiotis Kanavos
		{
350 4ec636f6 Panagiotis Kanavos
			/*var site = String.Format("{0}/ui/?token={1}&user={2}",
351 4ec636f6 Panagiotis Kanavos
				account.SiteUri,account.Token,
352 4ec636f6 Panagiotis Kanavos
				account.UserName);*/
353 4ec636f6 Panagiotis Kanavos
			Process.Start(account.SiteUri);
354 4ec636f6 Panagiotis Kanavos
		}
355 4ec636f6 Panagiotis Kanavos
356 4ec636f6 Panagiotis Kanavos
		public void ShowFileProperties()
357 4ec636f6 Panagiotis Kanavos
		{
358 4ec636f6 Panagiotis Kanavos
			var account = Settings.Accounts.First(acc => acc.IsActive);            
359 4ec636f6 Panagiotis Kanavos
			var dir = new DirectoryInfo(account.RootPath + @"\pithos");
360 4ec636f6 Panagiotis Kanavos
			var files=dir.GetFiles();
361 4ec636f6 Panagiotis Kanavos
			var r=new Random();
362 4ec636f6 Panagiotis Kanavos
			var idx=r.Next(0, files.Length);
363 4ec636f6 Panagiotis Kanavos
			ShowFileProperties(files[idx].FullName);            
364 4ec636f6 Panagiotis Kanavos
		}
365 4ec636f6 Panagiotis Kanavos
366 4ec636f6 Panagiotis Kanavos
		public void ShowFileProperties(string filePath)
367 4ec636f6 Panagiotis Kanavos
		{
368 4ec636f6 Panagiotis Kanavos
			if (String.IsNullOrWhiteSpace(filePath))
369 4ec636f6 Panagiotis Kanavos
				throw new ArgumentNullException("filePath");
370 4f6d51d4 Panagiotis Kanavos
			if (!File.Exists(filePath) && !Directory.Exists(filePath))
371 4ec636f6 Panagiotis Kanavos
				throw new ArgumentException(String.Format("Non existent file {0}",filePath),"filePath");
372 4ec636f6 Panagiotis Kanavos
			Contract.EndContractBlock();
373 4ec636f6 Panagiotis Kanavos
374 4ec636f6 Panagiotis Kanavos
			var pair=(from monitor in  Monitors
375 4ec636f6 Panagiotis Kanavos
							   where filePath.StartsWith(monitor.Value.RootPath, StringComparison.InvariantCultureIgnoreCase)
376 4ec636f6 Panagiotis Kanavos
								   select monitor).FirstOrDefault();
377 4f6d51d4 Panagiotis Kanavos
		    var accountMonitor = pair.Value;
378 4ec636f6 Panagiotis Kanavos
379 4ec636f6 Panagiotis Kanavos
			if (accountMonitor == null)
380 4ec636f6 Panagiotis Kanavos
				return;
381 4ec636f6 Panagiotis Kanavos
382 4ec636f6 Panagiotis Kanavos
			var infoTask=Task.Factory.StartNew(()=>accountMonitor.GetObjectInfo(filePath));
383 4ec636f6 Panagiotis Kanavos
384 4ec636f6 Panagiotis Kanavos
			
385 4ec636f6 Panagiotis Kanavos
386 4ec636f6 Panagiotis Kanavos
			var fileProperties = new FilePropertiesViewModel(this, infoTask,filePath);
387 4ec636f6 Panagiotis Kanavos
			_windowManager.ShowWindow(fileProperties);
388 4ec636f6 Panagiotis Kanavos
		} 
389 4ec636f6 Panagiotis Kanavos
		
390 4ec636f6 Panagiotis Kanavos
		public void ShowContainerProperties()
391 4ec636f6 Panagiotis Kanavos
		{
392 4ec636f6 Panagiotis Kanavos
			var account = Settings.Accounts.First(acc => acc.IsActive);            
393 4ec636f6 Panagiotis Kanavos
			var dir = new DirectoryInfo(account.RootPath);
394 4ec636f6 Panagiotis Kanavos
			var fullName = (from folder in dir.EnumerateDirectories()
395 4ec636f6 Panagiotis Kanavos
							where (folder.Attributes & FileAttributes.Hidden) == 0
396 4ec636f6 Panagiotis Kanavos
							select folder.FullName).First();
397 4ec636f6 Panagiotis Kanavos
			ShowContainerProperties(fullName);            
398 4ec636f6 Panagiotis Kanavos
		}
399 4ec636f6 Panagiotis Kanavos
400 4ec636f6 Panagiotis Kanavos
		public void ShowContainerProperties(string filePath)
401 4ec636f6 Panagiotis Kanavos
		{
402 4ec636f6 Panagiotis Kanavos
			if (String.IsNullOrWhiteSpace(filePath))
403 4ec636f6 Panagiotis Kanavos
				throw new ArgumentNullException("filePath");
404 4ec636f6 Panagiotis Kanavos
			if (!Directory.Exists(filePath))
405 4ec636f6 Panagiotis Kanavos
				throw new ArgumentException(String.Format("Non existent file {0}",filePath),"filePath");
406 4ec636f6 Panagiotis Kanavos
			Contract.EndContractBlock();
407 4ec636f6 Panagiotis Kanavos
408 4ec636f6 Panagiotis Kanavos
			var pair=(from monitor in  Monitors
409 4ec636f6 Panagiotis Kanavos
							   where filePath.StartsWith(monitor.Value.RootPath, StringComparison.InvariantCultureIgnoreCase)
410 4ec636f6 Panagiotis Kanavos
								   select monitor).FirstOrDefault();
411 4f6d51d4 Panagiotis Kanavos
		    var accountMonitor = pair.Value;            
412 4ec636f6 Panagiotis Kanavos
			var info = accountMonitor.GetContainerInfo(filePath);
413 4ec636f6 Panagiotis Kanavos
414 4ec636f6 Panagiotis Kanavos
			
415 4ec636f6 Panagiotis Kanavos
416 4ec636f6 Panagiotis Kanavos
			var containerProperties = new ContainerPropertiesViewModel(this, info,filePath);
417 4ec636f6 Panagiotis Kanavos
			_windowManager.ShowWindow(containerProperties);
418 4ec636f6 Panagiotis Kanavos
		}
419 4ec636f6 Panagiotis Kanavos
420 133f83c2 Panagiotis Kanavos
        public void SynchNow()
421 29a6b387 Panagiotis Kanavos
        {
422 29a6b387 Panagiotis Kanavos
            var agent = IoC.Get<NetworkAgent>();
423 29a6b387 Panagiotis Kanavos
            agent.SynchNow();
424 29a6b387 Panagiotis Kanavos
        }
425 133f83c2 Panagiotis Kanavos
426 4ec636f6 Panagiotis Kanavos
		public ObjectInfo RefreshObjectInfo(ObjectInfo currentInfo)
427 4ec636f6 Panagiotis Kanavos
		{
428 4ec636f6 Panagiotis Kanavos
			if (currentInfo==null)
429 4ec636f6 Panagiotis Kanavos
				throw new ArgumentNullException("currentInfo");
430 4ec636f6 Panagiotis Kanavos
			Contract.EndContractBlock();
431 4ec636f6 Panagiotis Kanavos
432 4ec636f6 Panagiotis Kanavos
			var monitor = Monitors[currentInfo.Account];
433 4ec636f6 Panagiotis Kanavos
			var newInfo=monitor.CloudClient.GetObjectInfo(currentInfo.Account, currentInfo.Container, currentInfo.Name);
434 4ec636f6 Panagiotis Kanavos
			return newInfo;
435 4ec636f6 Panagiotis Kanavos
		}
436 4ec636f6 Panagiotis Kanavos
437 4ec636f6 Panagiotis Kanavos
		public ContainerInfo RefreshContainerInfo(ContainerInfo container)
438 4ec636f6 Panagiotis Kanavos
		{
439 4ec636f6 Panagiotis Kanavos
			if (container == null)
440 4ec636f6 Panagiotis Kanavos
				throw new ArgumentNullException("container");
441 4ec636f6 Panagiotis Kanavos
			Contract.EndContractBlock();
442 4ec636f6 Panagiotis Kanavos
443 4ec636f6 Panagiotis Kanavos
			var monitor = Monitors[container.Account];
444 4ec636f6 Panagiotis Kanavos
			var newInfo = monitor.CloudClient.GetContainerInfo(container.Account, container.Name);
445 4ec636f6 Panagiotis Kanavos
			return newInfo;
446 4ec636f6 Panagiotis Kanavos
		}
447 4ec636f6 Panagiotis Kanavos
448 4ec636f6 Panagiotis Kanavos
449 4ec636f6 Panagiotis Kanavos
		public void ToggleSynching()
450 4ec636f6 Panagiotis Kanavos
		{
451 4ec636f6 Panagiotis Kanavos
			bool isPaused=false;
452 4ec636f6 Panagiotis Kanavos
			foreach (var pair in Monitors)
453 4ec636f6 Panagiotis Kanavos
			{
454 4ec636f6 Panagiotis Kanavos
				var monitor = pair.Value;
455 4ec636f6 Panagiotis Kanavos
				monitor.Pause = !monitor.Pause;
456 4ec636f6 Panagiotis Kanavos
				isPaused = monitor.Pause;
457 4ec636f6 Panagiotis Kanavos
			}
458 4ec636f6 Panagiotis Kanavos
459 4ec636f6 Panagiotis Kanavos
			PauseSyncCaption = isPaused ? "Resume syncing" : "Pause syncing";
460 4ec636f6 Panagiotis Kanavos
			var iconKey = isPaused? "TraySyncPaused" : "TrayInSynch";
461 4ec636f6 Panagiotis Kanavos
			StatusIcon = String.Format(@"../Images/{0}.ico", iconKey);
462 4ec636f6 Panagiotis Kanavos
		}
463 4ec636f6 Panagiotis Kanavos
464 4ec636f6 Panagiotis Kanavos
		public void ExitPithos()
465 4ec636f6 Panagiotis Kanavos
		{
466 4ec636f6 Panagiotis Kanavos
			foreach (var pair in Monitors)
467 4ec636f6 Panagiotis Kanavos
			{
468 4ec636f6 Panagiotis Kanavos
				var monitor = pair.Value;
469 4ec636f6 Panagiotis Kanavos
				monitor.Stop();
470 4ec636f6 Panagiotis Kanavos
			}
471 4ec636f6 Panagiotis Kanavos
472 4ec636f6 Panagiotis Kanavos
			((Window)GetView()).Close();
473 4ec636f6 Panagiotis Kanavos
		}
474 4ec636f6 Panagiotis Kanavos
		#endregion
475 4ec636f6 Panagiotis Kanavos
476 4ec636f6 Panagiotis Kanavos
477 4f6d51d4 Panagiotis Kanavos
		private readonly Dictionary<PithosStatus, StatusInfo> _iconNames = new List<StatusInfo>
478 4ec636f6 Panagiotis Kanavos
			{
479 4ec636f6 Panagiotis Kanavos
				new StatusInfo(PithosStatus.InSynch, "All files up to date", "TrayInSynch"),
480 4ec636f6 Panagiotis Kanavos
				new StatusInfo(PithosStatus.Syncing, "Syncing Files", "TraySynching"),
481 4ec636f6 Panagiotis Kanavos
				new StatusInfo(PithosStatus.SyncPaused, "Sync Paused", "TraySyncPaused")
482 4ec636f6 Panagiotis Kanavos
			}.ToDictionary(s => s.Status);
483 4ec636f6 Panagiotis Kanavos
484 4ec636f6 Panagiotis Kanavos
		readonly IWindowManager _windowManager;
485 422c9598 Panagiotis Kanavos
	    
486 c53aa229 Panagiotis Kanavos
487 cf761c0d Panagiotis Kanavos
		///<summary>
488 cf761c0d Panagiotis Kanavos
		/// Updates the visual status indicators of the application depending on status changes, e.g. icon, stat		
489 cf761c0d Panagiotis Kanavos
		///</summary>
490 4ec636f6 Panagiotis Kanavos
		public void UpdateStatus()
491 4ec636f6 Panagiotis Kanavos
		{
492 4ec636f6 Panagiotis Kanavos
			var pithosStatus = _statusChecker.GetPithosStatus();
493 4ec636f6 Panagiotis Kanavos
494 4f6d51d4 Panagiotis Kanavos
			if (_iconNames.ContainsKey(pithosStatus))
495 4ec636f6 Panagiotis Kanavos
			{
496 4f6d51d4 Panagiotis Kanavos
				var info = _iconNames[pithosStatus];
497 4ec636f6 Panagiotis Kanavos
				StatusIcon = String.Format(@"../Images/{0}.ico", info.IconName);
498 4ec636f6 Panagiotis Kanavos
499 4ec636f6 Panagiotis Kanavos
500 4ec636f6 Panagiotis Kanavos
501 422c9598 Panagiotis Kanavos
				StatusMessage = String.Format("Pithos {0}\r\n{1}", _fileVersion.Value.FileVersion,info.StatusText);
502 4ec636f6 Panagiotis Kanavos
			}
503 4ec636f6 Panagiotis Kanavos
			
504 852d2cf2 Panagiotis Kanavos
			//_events.Publish(new Notification { Title = "Start", Message = "Start Monitoring", Level = TraceLevel.Info});
505 4ec636f6 Panagiotis Kanavos
		}
506 4ec636f6 Panagiotis Kanavos
507 4ec636f6 Panagiotis Kanavos
508 4ec636f6 Panagiotis Kanavos
	   
509 4ec636f6 Panagiotis Kanavos
		private Task StartMonitor(PithosMonitor monitor,int retries=0)
510 4ec636f6 Panagiotis Kanavos
		{
511 4ec636f6 Panagiotis Kanavos
			return Task.Factory.StartNew(() =>
512 4ec636f6 Panagiotis Kanavos
			{
513 4ec636f6 Panagiotis Kanavos
				using (log4net.ThreadContext.Stacks["Monitor"].Push("Start"))
514 4ec636f6 Panagiotis Kanavos
				{
515 4ec636f6 Panagiotis Kanavos
					try
516 4ec636f6 Panagiotis Kanavos
					{
517 4ec636f6 Panagiotis Kanavos
						Log.InfoFormat("Start Monitoring {0}", monitor.UserName);
518 4ec636f6 Panagiotis Kanavos
519 4ec636f6 Panagiotis Kanavos
						monitor.Start();
520 4ec636f6 Panagiotis Kanavos
					}
521 4ec636f6 Panagiotis Kanavos
					catch (WebException exc)
522 4ec636f6 Panagiotis Kanavos
					{
523 4ec636f6 Panagiotis Kanavos
						if (AbandonRetry(monitor, retries))
524 4ec636f6 Panagiotis Kanavos
							return;
525 4ec636f6 Panagiotis Kanavos
526 65282d58 Panagiotis Kanavos
                        HttpStatusCode statusCode =HttpStatusCode.OK;
527 65282d58 Panagiotis Kanavos
			            var response = exc.Response as HttpWebResponse;
528 65282d58 Panagiotis Kanavos
                        if(response!=null)
529 65282d58 Panagiotis Kanavos
					        statusCode = response.StatusCode;
530 65282d58 Panagiotis Kanavos
531 65282d58 Panagiotis Kanavos
                        switch (statusCode)
532 65282d58 Panagiotis Kanavos
                        {
533 65282d58 Panagiotis Kanavos
                            case HttpStatusCode.Unauthorized:
534 65282d58 Panagiotis Kanavos
                                var message = String.Format("API Key Expired for {0}. Starting Renewal",
535 65282d58 Panagiotis Kanavos
                                                            monitor.UserName);
536 65282d58 Panagiotis Kanavos
                                Log.Error(message, exc);
537 65282d58 Panagiotis Kanavos
                                TryAuthorize(monitor, retries).Wait();
538 65282d58 Panagiotis Kanavos
                                break;
539 65282d58 Panagiotis Kanavos
                            case HttpStatusCode.ProxyAuthenticationRequired:
540 65282d58 Panagiotis Kanavos
                                TryAuthenticateProxy(monitor,retries);
541 65282d58 Panagiotis Kanavos
                                break;
542 65282d58 Panagiotis Kanavos
                            default:
543 65282d58 Panagiotis Kanavos
                                TryLater(monitor, exc, retries);
544 65282d58 Panagiotis Kanavos
                                break;
545 65282d58 Panagiotis Kanavos
                        }
546 4ec636f6 Panagiotis Kanavos
					}
547 4ec636f6 Panagiotis Kanavos
					catch (Exception exc)
548 4ec636f6 Panagiotis Kanavos
					{
549 4ec636f6 Panagiotis Kanavos
						if (AbandonRetry(monitor, retries)) 
550 4ec636f6 Panagiotis Kanavos
							return;
551 4ec636f6 Panagiotis Kanavos
552 4ec636f6 Panagiotis Kanavos
						TryLater(monitor,exc,retries);
553 4ec636f6 Panagiotis Kanavos
					}
554 4ec636f6 Panagiotis Kanavos
				}
555 4ec636f6 Panagiotis Kanavos
			});
556 4ec636f6 Panagiotis Kanavos
		}
557 4ec636f6 Panagiotis Kanavos
558 65282d58 Panagiotis Kanavos
	    private void TryAuthenticateProxy(PithosMonitor monitor,int retries)
559 65282d58 Panagiotis Kanavos
	    {
560 65282d58 Panagiotis Kanavos
	        Execute.OnUIThread(() =>
561 65282d58 Panagiotis Kanavos
	                               {
562 65282d58 Panagiotis Kanavos
	                                   var proxyAccount = new ProxyAccountViewModel(this.Settings);
563 65282d58 Panagiotis Kanavos
	                                   if (true == _windowManager.ShowDialog(proxyAccount))
564 65282d58 Panagiotis Kanavos
	                                   {
565 65282d58 Panagiotis Kanavos
                                           
566 65282d58 Panagiotis Kanavos
	                                       StartMonitor(monitor, retries);
567 65282d58 Panagiotis Kanavos
	                                       NotifyOfPropertyChange(() => Accounts);
568 65282d58 Panagiotis Kanavos
	                                   }
569 65282d58 Panagiotis Kanavos
	                               });
570 65282d58 Panagiotis Kanavos
	    }
571 65282d58 Panagiotis Kanavos
572 65282d58 Panagiotis Kanavos
	    private bool AbandonRetry(PithosMonitor monitor, int retries)
573 4ec636f6 Panagiotis Kanavos
		{
574 4ec636f6 Panagiotis Kanavos
			if (retries > 1)
575 4ec636f6 Panagiotis Kanavos
			{
576 4ec636f6 Panagiotis Kanavos
				var message = String.Format("Monitoring of account {0} has failed too many times. Will not retry",
577 4ec636f6 Panagiotis Kanavos
											monitor.UserName);
578 4ec636f6 Panagiotis Kanavos
				_events.Publish(new Notification
579 4ec636f6 Panagiotis Kanavos
									{Title = "Account monitoring failed", Message = message, Level = TraceLevel.Error});
580 4ec636f6 Panagiotis Kanavos
				return true;
581 4ec636f6 Panagiotis Kanavos
			}
582 4ec636f6 Panagiotis Kanavos
			return false;
583 4ec636f6 Panagiotis Kanavos
		}
584 4ec636f6 Panagiotis Kanavos
585 4ec636f6 Panagiotis Kanavos
586 4ec636f6 Panagiotis Kanavos
		private async Task TryAuthorize(PithosMonitor monitor,int retries)
587 4ec636f6 Panagiotis Kanavos
		{
588 4ec636f6 Panagiotis Kanavos
			_events.Publish(new Notification { Title = "Authorization failed", Message = "Your API Key has probably expired. You will be directed to a page where you can renew it", Level = TraceLevel.Error });
589 4ec636f6 Panagiotis Kanavos
590 4ec636f6 Panagiotis Kanavos
			try
591 4ec636f6 Panagiotis Kanavos
			{
592 4ec636f6 Panagiotis Kanavos
593 4ec636f6 Panagiotis Kanavos
				var credentials = await PithosAccount.RetrieveCredentials(Settings.PithosLoginUrl);
594 4ec636f6 Panagiotis Kanavos
595 4f6d51d4 Panagiotis Kanavos
				var account = Settings.Accounts.First(act => act.AccountName == credentials.UserName);
596 4ec636f6 Panagiotis Kanavos
				account.ApiKey = credentials.Password;
597 4ec636f6 Panagiotis Kanavos
				monitor.ApiKey = credentials.Password;
598 4ec636f6 Panagiotis Kanavos
				Settings.Save();
599 4ec636f6 Panagiotis Kanavos
				await TaskEx.Delay(10000);
600 4ec636f6 Panagiotis Kanavos
				StartMonitor(monitor, retries + 1);
601 4ec636f6 Panagiotis Kanavos
				NotifyOfPropertyChange(()=>Accounts);
602 4ec636f6 Panagiotis Kanavos
			}
603 4ec636f6 Panagiotis Kanavos
			catch (AggregateException exc)
604 4ec636f6 Panagiotis Kanavos
			{
605 4ec636f6 Panagiotis Kanavos
				string message = String.Format("API Key retrieval for {0} failed", monitor.UserName);
606 4ec636f6 Panagiotis Kanavos
				Log.Error(message, exc.InnerException);
607 4ec636f6 Panagiotis Kanavos
				_events.Publish(new Notification { Title = "Authorization failed", Message = message, Level = TraceLevel.Error });
608 4ec636f6 Panagiotis Kanavos
			}
609 4ec636f6 Panagiotis Kanavos
			catch (Exception exc)
610 4ec636f6 Panagiotis Kanavos
			{
611 4ec636f6 Panagiotis Kanavos
				string message = String.Format("API Key retrieval for {0} failed", monitor.UserName);
612 4ec636f6 Panagiotis Kanavos
				Log.Error(message, exc);
613 4ec636f6 Panagiotis Kanavos
				_events.Publish(new Notification { Title = "Authorization failed", Message = message, Level = TraceLevel.Error });
614 4ec636f6 Panagiotis Kanavos
			}
615 4ec636f6 Panagiotis Kanavos
616 4ec636f6 Panagiotis Kanavos
		}
617 4ec636f6 Panagiotis Kanavos
618 4ec636f6 Panagiotis Kanavos
		private static bool IsUnauthorized(WebException exc)
619 4ec636f6 Panagiotis Kanavos
		{
620 4ec636f6 Panagiotis Kanavos
			if (exc==null)
621 4ec636f6 Panagiotis Kanavos
				throw new ArgumentNullException("exc");
622 4ec636f6 Panagiotis Kanavos
			Contract.EndContractBlock();
623 4ec636f6 Panagiotis Kanavos
624 4ec636f6 Panagiotis Kanavos
			var response = exc.Response as HttpWebResponse;
625 4ec636f6 Panagiotis Kanavos
			if (response == null)
626 4ec636f6 Panagiotis Kanavos
				return false;
627 4ec636f6 Panagiotis Kanavos
			return (response.StatusCode == HttpStatusCode.Unauthorized);
628 4ec636f6 Panagiotis Kanavos
		}
629 4ec636f6 Panagiotis Kanavos
630 4ec636f6 Panagiotis Kanavos
		private void TryLater(PithosMonitor monitor, Exception exc,int retries)
631 4ec636f6 Panagiotis Kanavos
		{
632 4ec636f6 Panagiotis Kanavos
			var message = String.Format("An exception occured. Can't start monitoring\nWill retry in 10 seconds");
633 4ec636f6 Panagiotis Kanavos
			Task.Factory.StartNewDelayed(10000, () => StartMonitor(monitor,retries+1));
634 4ec636f6 Panagiotis Kanavos
			_events.Publish(new Notification
635 4ec636f6 Panagiotis Kanavos
								{Title = "Error", Message = message, Level = TraceLevel.Error});
636 4ec636f6 Panagiotis Kanavos
			Log.Error(message, exc);
637 4ec636f6 Panagiotis Kanavos
		}
638 4ec636f6 Panagiotis Kanavos
639 4ec636f6 Panagiotis Kanavos
640 4ec636f6 Panagiotis Kanavos
		public void NotifyChange(string status, TraceLevel level=TraceLevel.Info)
641 4ec636f6 Panagiotis Kanavos
		{
642 4f6d51d4 Panagiotis Kanavos
			StatusMessage = status;
643 4ec636f6 Panagiotis Kanavos
			
644 4ec636f6 Panagiotis Kanavos
			_events.Publish(new Notification { Title = "Pithos", Message = status, Level = level });
645 4ec636f6 Panagiotis Kanavos
		}
646 4ec636f6 Panagiotis Kanavos
647 4ec636f6 Panagiotis Kanavos
		public void NotifyChangedFile(string filePath)
648 4ec636f6 Panagiotis Kanavos
		{
649 4ec636f6 Panagiotis Kanavos
			var entry = new FileEntry {FullPath=filePath};
650 4f6d51d4 Panagiotis Kanavos
			IProducerConsumerCollection<FileEntry> files=RecentFiles;
651 4ec636f6 Panagiotis Kanavos
			FileEntry popped;
652 4ec636f6 Panagiotis Kanavos
			while (files.Count > 5)
653 4ec636f6 Panagiotis Kanavos
				files.TryTake(out popped);
654 4ec636f6 Panagiotis Kanavos
			files.TryAdd(entry);
655 4ec636f6 Panagiotis Kanavos
		}
656 4ec636f6 Panagiotis Kanavos
657 4ec636f6 Panagiotis Kanavos
		public void NotifyAccount(AccountInfo account)
658 4ec636f6 Panagiotis Kanavos
		{
659 4ec636f6 Panagiotis Kanavos
			if (account== null)
660 4ec636f6 Panagiotis Kanavos
				return;
661 4ec636f6 Panagiotis Kanavos
			//TODO: What happens to an existing account whose Token has changed?
662 4ec636f6 Panagiotis Kanavos
			account.SiteUri= String.Format("{0}/ui/?token={1}&user={2}",
663 eae84ae8 Panagiotis Kanavos
				account.SiteUri, Uri.EscapeDataString(account.Token),
664 eae84ae8 Panagiotis Kanavos
                Uri.EscapeDataString(account.UserName));
665 4ec636f6 Panagiotis Kanavos
666 4ec636f6 Panagiotis Kanavos
			if (Accounts.All(item => item.UserName != account.UserName))
667 4ec636f6 Panagiotis Kanavos
				Accounts.TryAdd(account);
668 4ec636f6 Panagiotis Kanavos
669 4ec636f6 Panagiotis Kanavos
		}
670 4ec636f6 Panagiotis Kanavos
671 9c6d3193 Panagiotis Kanavos
	    public void NotifyConflicts(IEnumerable<FileSystemInfo> conflictFiles, string message)
672 9c6d3193 Panagiotis Kanavos
	    {
673 9c6d3193 Panagiotis Kanavos
            if (conflictFiles == null)
674 9c6d3193 Panagiotis Kanavos
                return;
675 9c6d3193 Panagiotis Kanavos
            if (!conflictFiles.Any())
676 9c6d3193 Panagiotis Kanavos
                return;
677 e5b65606 Panagiotis Kanavos
678 e5b65606 Panagiotis Kanavos
            UpdateStatus();
679 9c6d3193 Panagiotis Kanavos
            //TODO: Create a more specific message. For now, just show a warning
680 9c6d3193 Panagiotis Kanavos
            NotifyForFiles(conflictFiles,message,TraceLevel.Warning);
681 9c6d3193 Panagiotis Kanavos
682 9c6d3193 Panagiotis Kanavos
	    }
683 9c6d3193 Panagiotis Kanavos
684 9c6d3193 Panagiotis Kanavos
	    public void NotifyForFiles(IEnumerable<FileSystemInfo> files, string message,TraceLevel level=TraceLevel.Info)
685 9c6d3193 Panagiotis Kanavos
	    {
686 9c6d3193 Panagiotis Kanavos
            if (files == null)
687 9c6d3193 Panagiotis Kanavos
                return;
688 9c6d3193 Panagiotis Kanavos
            if (!files.Any())
689 9c6d3193 Panagiotis Kanavos
                return;
690 9c6d3193 Panagiotis Kanavos
691 9c6d3193 Panagiotis Kanavos
            StatusMessage = message;
692 9c6d3193 Panagiotis Kanavos
693 9c6d3193 Panagiotis Kanavos
            _events.Publish(new Notification { Title = "Pithos", Message = message, Level = level});
694 9c6d3193 Panagiotis Kanavos
        }
695 9c6d3193 Panagiotis Kanavos
696 e5b65606 Panagiotis Kanavos
        public void Notify(Notification notification)
697 e5b65606 Panagiotis Kanavos
        {
698 e5b65606 Panagiotis Kanavos
            _events.Publish(notification);
699 e5b65606 Panagiotis Kanavos
        }
700 e5b65606 Panagiotis Kanavos
701 4ec636f6 Panagiotis Kanavos
702 9c6d3193 Panagiotis Kanavos
	    public void RemoveMonitor(string accountName)
703 4ec636f6 Panagiotis Kanavos
		{
704 4ec636f6 Panagiotis Kanavos
			if (String.IsNullOrWhiteSpace(accountName))
705 4ec636f6 Panagiotis Kanavos
				return;
706 4ec636f6 Panagiotis Kanavos
707 4ec636f6 Panagiotis Kanavos
			var accountInfo=_accounts.FirstOrDefault(account => account.UserName == accountName);
708 4ec636f6 Panagiotis Kanavos
			_accounts.TryRemove(accountInfo);
709 4ec636f6 Panagiotis Kanavos
710 4ec636f6 Panagiotis Kanavos
			PithosMonitor monitor;
711 4ec636f6 Panagiotis Kanavos
			if (Monitors.TryRemove(accountName, out monitor))
712 4ec636f6 Panagiotis Kanavos
			{
713 4ec636f6 Panagiotis Kanavos
				monitor.Stop();
714 4ec636f6 Panagiotis Kanavos
			}
715 4ec636f6 Panagiotis Kanavos
		}
716 4ec636f6 Panagiotis Kanavos
717 4ec636f6 Panagiotis Kanavos
		public void RefreshOverlays()
718 4ec636f6 Panagiotis Kanavos
		{
719 4ec636f6 Panagiotis Kanavos
			foreach (var pair in Monitors)
720 4ec636f6 Panagiotis Kanavos
			{
721 4ec636f6 Panagiotis Kanavos
				var monitor = pair.Value;
722 4ec636f6 Panagiotis Kanavos
723 4ec636f6 Panagiotis Kanavos
				var path = monitor.RootPath;
724 4ec636f6 Panagiotis Kanavos
725 4ec636f6 Panagiotis Kanavos
				if (String.IsNullOrWhiteSpace(path))
726 4ec636f6 Panagiotis Kanavos
					continue;
727 4ec636f6 Panagiotis Kanavos
728 4ec636f6 Panagiotis Kanavos
				if (!Directory.Exists(path) && !File.Exists(path))
729 4ec636f6 Panagiotis Kanavos
					continue;
730 4ec636f6 Panagiotis Kanavos
731 4ec636f6 Panagiotis Kanavos
				IntPtr pathPointer = Marshal.StringToCoTaskMemAuto(path);
732 4ec636f6 Panagiotis Kanavos
733 4ec636f6 Panagiotis Kanavos
				try
734 4ec636f6 Panagiotis Kanavos
				{
735 4ec636f6 Panagiotis Kanavos
					NativeMethods.SHChangeNotify(HChangeNotifyEventID.SHCNE_UPDATEITEM,
736 4ec636f6 Panagiotis Kanavos
												 HChangeNotifyFlags.SHCNF_PATHW | HChangeNotifyFlags.SHCNF_FLUSHNOWAIT,
737 4ec636f6 Panagiotis Kanavos
												 pathPointer, IntPtr.Zero);
738 4ec636f6 Panagiotis Kanavos
				}
739 4ec636f6 Panagiotis Kanavos
				finally
740 4ec636f6 Panagiotis Kanavos
				{
741 4ec636f6 Panagiotis Kanavos
					Marshal.FreeHGlobal(pathPointer);
742 4ec636f6 Panagiotis Kanavos
				}
743 4ec636f6 Panagiotis Kanavos
			}
744 4ec636f6 Panagiotis Kanavos
		}
745 4ec636f6 Panagiotis Kanavos
746 4ec636f6 Panagiotis Kanavos
		#region Event Handlers
747 4ec636f6 Panagiotis Kanavos
		
748 4ec636f6 Panagiotis Kanavos
		public void Handle(SelectiveSynchChanges message)
749 4ec636f6 Panagiotis Kanavos
		{
750 4ec636f6 Panagiotis Kanavos
			var accountName = message.Account.AccountName;
751 4ec636f6 Panagiotis Kanavos
			PithosMonitor monitor;
752 4ec636f6 Panagiotis Kanavos
			if (_monitors.TryGetValue(accountName, out monitor))
753 4ec636f6 Panagiotis Kanavos
			{
754 4ec636f6 Panagiotis Kanavos
				monitor.AddSelectivePaths(message.Added);
755 4ec636f6 Panagiotis Kanavos
				monitor.RemoveSelectivePaths(message.Removed);
756 4ec636f6 Panagiotis Kanavos
757 4ec636f6 Panagiotis Kanavos
			}
758 4ec636f6 Panagiotis Kanavos
			
759 4ec636f6 Panagiotis Kanavos
		}
760 4ec636f6 Panagiotis Kanavos
761 4ec636f6 Panagiotis Kanavos
762 eae84ae8 Panagiotis Kanavos
	    private bool _pollStarted = false;
763 eae84ae8 Panagiotis Kanavos
764 025046f1 Panagiotis Kanavos
        //SMELL: Doing so much work for notifications in the shell is wrong
765 025046f1 Panagiotis Kanavos
        //The notifications should be moved to their own view/viewmodel pair
766 025046f1 Panagiotis Kanavos
        //and different templates should be used for different message types
767 025046f1 Panagiotis Kanavos
        //This will also allow the addition of extra functionality, eg. actions
768 e5b65606 Panagiotis Kanavos
        //
769 4ec636f6 Panagiotis Kanavos
		public void Handle(Notification notification)
770 4ec636f6 Panagiotis Kanavos
		{
771 e5b65606 Panagiotis Kanavos
            UpdateStatus();
772 e5b65606 Panagiotis Kanavos
773 4ec636f6 Panagiotis Kanavos
			if (!Settings.ShowDesktopNotifications)
774 4ec636f6 Panagiotis Kanavos
				return;
775 eae84ae8 Panagiotis Kanavos
776 eae84ae8 Panagiotis Kanavos
            if (notification is PollNotification)
777 eae84ae8 Panagiotis Kanavos
            {
778 eae84ae8 Panagiotis Kanavos
                _pollStarted = true;
779 eae84ae8 Panagiotis Kanavos
                return;
780 eae84ae8 Panagiotis Kanavos
            }
781 eae84ae8 Panagiotis Kanavos
            if (notification is CloudNotification)
782 eae84ae8 Panagiotis Kanavos
            {
783 eae84ae8 Panagiotis Kanavos
                if (!_pollStarted) 
784 eae84ae8 Panagiotis Kanavos
                    return;
785 eae84ae8 Panagiotis Kanavos
                _pollStarted= false;
786 eae84ae8 Panagiotis Kanavos
                notification.Title = "Pithos";
787 eae84ae8 Panagiotis Kanavos
                notification.Message = "Start Synchronisation";
788 eae84ae8 Panagiotis Kanavos
            }
789 eae84ae8 Panagiotis Kanavos
790 2dc6f765 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(notification.Message) && String.IsNullOrWhiteSpace(notification.Title))
791 2dc6f765 Panagiotis Kanavos
                return;
792 2dc6f765 Panagiotis Kanavos
793 4f6d51d4 Panagiotis Kanavos
			BalloonIcon icon;
794 4ec636f6 Panagiotis Kanavos
			switch (notification.Level)
795 4ec636f6 Panagiotis Kanavos
			{
796 4ec636f6 Panagiotis Kanavos
				case TraceLevel.Error:
797 4ec636f6 Panagiotis Kanavos
					icon = BalloonIcon.Error;
798 4ec636f6 Panagiotis Kanavos
					break;
799 4ec636f6 Panagiotis Kanavos
				case TraceLevel.Info:
800 4ec636f6 Panagiotis Kanavos
				case TraceLevel.Verbose:
801 4ec636f6 Panagiotis Kanavos
					icon = BalloonIcon.Info;
802 4ec636f6 Panagiotis Kanavos
					break;
803 4ec636f6 Panagiotis Kanavos
				case TraceLevel.Warning:
804 4ec636f6 Panagiotis Kanavos
					icon = BalloonIcon.Warning;
805 4ec636f6 Panagiotis Kanavos
					break;
806 4ec636f6 Panagiotis Kanavos
				default:
807 4ec636f6 Panagiotis Kanavos
					icon = BalloonIcon.None;
808 4ec636f6 Panagiotis Kanavos
					break;
809 4ec636f6 Panagiotis Kanavos
			}
810 eae84ae8 Panagiotis Kanavos
            
811 4ec636f6 Panagiotis Kanavos
			if (Settings.ShowDesktopNotifications)
812 4ec636f6 Panagiotis Kanavos
			{
813 eae84ae8 Panagiotis Kanavos
				var tv = (ShellView) GetView();                
814 2dc6f765 Panagiotis Kanavos
                var balloon=new PithosBalloon{Title=notification.Title,Message=notification.Message,Icon=icon};
815 fb9d6e00 Panagiotis Kanavos
                tv.TaskbarView.ShowCustomBalloon(balloon,PopupAnimation.Fade,4000);
816 fb9d6e00 Panagiotis Kanavos
//				tv.TaskbarView.ShowBalloonTip(notification.Title, notification.Message, icon);
817 4ec636f6 Panagiotis Kanavos
			}
818 4ec636f6 Panagiotis Kanavos
		}
819 4ec636f6 Panagiotis Kanavos
		#endregion
820 4ec636f6 Panagiotis Kanavos
821 4ec636f6 Panagiotis Kanavos
		public void Handle(ShowFilePropertiesEvent message)
822 4ec636f6 Panagiotis Kanavos
		{
823 4ec636f6 Panagiotis Kanavos
			if (message == null)
824 4ec636f6 Panagiotis Kanavos
				throw new ArgumentNullException("message");
825 4ec636f6 Panagiotis Kanavos
			if (String.IsNullOrWhiteSpace(message.FileName) )
826 4ec636f6 Panagiotis Kanavos
				throw new ArgumentException("message");
827 4ec636f6 Panagiotis Kanavos
			Contract.EndContractBlock();
828 4ec636f6 Panagiotis Kanavos
829 4ec636f6 Panagiotis Kanavos
			var fileName = message.FileName;
830 4f6d51d4 Panagiotis Kanavos
            //TODO: Display file properties for non-container folders
831 4ec636f6 Panagiotis Kanavos
			if (File.Exists(fileName))
832 4f6d51d4 Panagiotis Kanavos
                //Retrieve the full name with exact casing. Pithos names are case sensitive				
833 f3d080df Panagiotis Kanavos
                ShowFileProperties(FileInfoExtensions.GetProperFilePathCapitalization(fileName));
834 4ec636f6 Panagiotis Kanavos
			else if (Directory.Exists(fileName))
835 4f6d51d4 Panagiotis Kanavos
                //Retrieve the full name with exact casing. Pithos names are case sensitive
836 4f6d51d4 Panagiotis Kanavos
			{
837 f3d080df Panagiotis Kanavos
                var path = FileInfoExtensions.GetProperDirectoryCapitalization(fileName);
838 4f6d51d4 Panagiotis Kanavos
                if (IsContainer(path))
839 4f6d51d4 Panagiotis Kanavos
			        ShowContainerProperties(path);
840 4f6d51d4 Panagiotis Kanavos
                else
841 4f6d51d4 Panagiotis Kanavos
                    ShowFileProperties(path);
842 4f6d51d4 Panagiotis Kanavos
			}
843 4ec636f6 Panagiotis Kanavos
		}
844 4f6d51d4 Panagiotis Kanavos
845 4f6d51d4 Panagiotis Kanavos
	    private bool IsContainer(string path)
846 4f6d51d4 Panagiotis Kanavos
	    {
847 4f6d51d4 Panagiotis Kanavos
	        var matchingFolders = from account in _accounts
848 4f6d51d4 Panagiotis Kanavos
	                              from rootFolder in Directory.GetDirectories(account.AccountPath)
849 4f6d51d4 Panagiotis Kanavos
	                              where rootFolder.Equals(path, StringComparison.InvariantCultureIgnoreCase)
850 4f6d51d4 Panagiotis Kanavos
	                              select rootFolder;
851 4f6d51d4 Panagiotis Kanavos
	        return matchingFolders.Any();
852 4f6d51d4 Panagiotis Kanavos
	    }
853 4f6d51d4 Panagiotis Kanavos
854 025046f1 Panagiotis Kanavos
	    public FileStatus GetFileStatus(string localFileName)
855 025046f1 Panagiotis Kanavos
	    {
856 025046f1 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(localFileName))
857 025046f1 Panagiotis Kanavos
                throw new ArgumentNullException("localFileName");
858 025046f1 Panagiotis Kanavos
            Contract.EndContractBlock();
859 025046f1 Panagiotis Kanavos
            
860 025046f1 Panagiotis Kanavos
	        var statusKeeper = IoC.Get<IStatusKeeper>();
861 025046f1 Panagiotis Kanavos
	        var status=statusKeeper.GetFileStatus(localFileName);
862 025046f1 Panagiotis Kanavos
	        return status;
863 025046f1 Panagiotis Kanavos
	    }
864 4ec636f6 Panagiotis Kanavos
	}
865 9bae55d1 Panagiotis Kanavos
}