Statistics
| Branch: | Revision:

root / trunk / Pithos.Client.WPF / Shell / ShellViewModel.cs @ 31c97141

History | View | Annotate | Download (25.6 kB)

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