Statistics
| Branch: | Revision:

root / trunk / Pithos.Client.WPF / Shell / ShellViewModel.cs @ 2797b5ef

History | View | Annotate | Download (26.1 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 c636df1f Panagiotis Kanavos
                    if (account.IsActive)
236 c636df1f Panagiotis Kanavos
                    {
237 c636df1f Panagiotis Kanavos
                        //The Api Key may have changed throuth the Preferences dialog
238 c636df1f Panagiotis Kanavos
                        monitor.ApiKey = account.ApiKey;
239 c636df1f Panagiotis Kanavos
						Debug.Assert(monitor.StatusNotification == this,"An existing monitor should already have a StatusNotification service object");
240 c636df1f Panagiotis Kanavos
                        monitor.RootPath = account.RootPath;
241 c636df1f Panagiotis Kanavos
                        //Start the monitor. It's OK to start an already started monitor,
242 c636df1f Panagiotis Kanavos
                        //it will just ignore the call                        
243 c636df1f Panagiotis Kanavos
                        StartMonitor(monitor).Wait();
244 c636df1f Panagiotis Kanavos
                    }
245 c636df1f Panagiotis Kanavos
                    else
246 c636df1f Panagiotis Kanavos
                    {
247 c636df1f Panagiotis Kanavos
                        //If the account is inactive
248 c636df1f Panagiotis Kanavos
                        //Stop and remove the monitor
249 c636df1f Panagiotis Kanavos
                        RemoveMonitor(accountName);
250 c636df1f Panagiotis Kanavos
                    }
251 4ec636f6 Panagiotis Kanavos
					return;
252 4ec636f6 Panagiotis Kanavos
				}
253 4ec636f6 Panagiotis Kanavos
254 255f5f86 Panagiotis Kanavos
				
255 4ec636f6 Panagiotis Kanavos
				//Create a new monitor/ Can't use MEF here, it would return a single instance for all monitors
256 4ec636f6 Panagiotis Kanavos
				monitor = new PithosMonitor
257 4ec636f6 Panagiotis Kanavos
							  {
258 4ec636f6 Panagiotis Kanavos
								  UserName = accountName,
259 4ec636f6 Panagiotis Kanavos
								  ApiKey = account.ApiKey,                                  
260 4ec636f6 Panagiotis Kanavos
								  StatusNotification = this,
261 4ec636f6 Panagiotis Kanavos
								  RootPath = account.RootPath
262 4ec636f6 Panagiotis Kanavos
							  };
263 4ec636f6 Panagiotis Kanavos
				//PithosMonitor uses MEF so we need to resolve it
264 4ec636f6 Panagiotis Kanavos
				IoC.BuildUp(monitor);
265 4ec636f6 Panagiotis Kanavos
266 255f5f86 Panagiotis Kanavos
				monitor.AuthenticationUrl = account.ServerUrl;
267 4ec636f6 Panagiotis Kanavos
268 4ec636f6 Panagiotis Kanavos
				_monitors[accountName] = monitor;
269 4ec636f6 Panagiotis Kanavos
270 4ec636f6 Panagiotis Kanavos
				if (account.IsActive)
271 4ec636f6 Panagiotis Kanavos
				{
272 4ec636f6 Panagiotis Kanavos
					//Don't start a monitor if it doesn't have an account and ApiKey
273 4ec636f6 Panagiotis Kanavos
					if (String.IsNullOrWhiteSpace(monitor.UserName) ||
274 4ec636f6 Panagiotis Kanavos
						String.IsNullOrWhiteSpace(monitor.ApiKey))
275 4ec636f6 Panagiotis Kanavos
						return;
276 4ec636f6 Panagiotis Kanavos
					StartMonitor(monitor);
277 4ec636f6 Panagiotis Kanavos
				}
278 4ec636f6 Panagiotis Kanavos
			});
279 4ec636f6 Panagiotis Kanavos
		}
280 4ec636f6 Panagiotis Kanavos
281 4ec636f6 Panagiotis Kanavos
282 4ec636f6 Panagiotis Kanavos
		protected override void OnViewLoaded(object view)
283 4ec636f6 Panagiotis Kanavos
		{
284 4ec636f6 Panagiotis Kanavos
			UpdateStatus();
285 4ec636f6 Panagiotis Kanavos
			var window = (Window)view;            
286 4ec636f6 Panagiotis Kanavos
			TaskEx.Delay(1000).ContinueWith(t => Execute.OnUIThread(window.Hide));
287 4ec636f6 Panagiotis Kanavos
			base.OnViewLoaded(view);
288 4ec636f6 Panagiotis Kanavos
		}
289 4ec636f6 Panagiotis Kanavos
290 4ec636f6 Panagiotis Kanavos
291 4ec636f6 Panagiotis Kanavos
		#region Status Properties
292 4ec636f6 Panagiotis Kanavos
293 4ec636f6 Panagiotis Kanavos
		private string _statusMessage;
294 4ec636f6 Panagiotis Kanavos
		public string StatusMessage
295 4ec636f6 Panagiotis Kanavos
		{
296 4ec636f6 Panagiotis Kanavos
			get { return _statusMessage; }
297 4ec636f6 Panagiotis Kanavos
			set
298 4ec636f6 Panagiotis Kanavos
			{
299 4ec636f6 Panagiotis Kanavos
				_statusMessage = value;
300 4ec636f6 Panagiotis Kanavos
				NotifyOfPropertyChange(() => StatusMessage);
301 4ec636f6 Panagiotis Kanavos
			}
302 4ec636f6 Panagiotis Kanavos
		}
303 4ec636f6 Panagiotis Kanavos
304 4ec636f6 Panagiotis Kanavos
		private readonly ObservableConcurrentCollection<AccountInfo> _accounts = new ObservableConcurrentCollection<AccountInfo>();
305 4ec636f6 Panagiotis Kanavos
		public ObservableConcurrentCollection<AccountInfo> Accounts
306 4ec636f6 Panagiotis Kanavos
		{
307 4ec636f6 Panagiotis Kanavos
			get { return _accounts; }
308 4ec636f6 Panagiotis Kanavos
		}
309 4ec636f6 Panagiotis Kanavos
310 4ec636f6 Panagiotis Kanavos
		public bool HasAccounts
311 4ec636f6 Panagiotis Kanavos
		{
312 4ec636f6 Panagiotis Kanavos
			get { return _accounts.Count > 0; }
313 4ec636f6 Panagiotis Kanavos
		}
314 4ec636f6 Panagiotis Kanavos
315 4ec636f6 Panagiotis Kanavos
316 4ec636f6 Panagiotis Kanavos
		public string OpenFolderCaption
317 4ec636f6 Panagiotis Kanavos
		{
318 4ec636f6 Panagiotis Kanavos
			get
319 4ec636f6 Panagiotis Kanavos
			{
320 4ec636f6 Panagiotis Kanavos
				return (_accounts.Count == 0)
321 4ec636f6 Panagiotis Kanavos
						? "No Accounts Defined"
322 4ec636f6 Panagiotis Kanavos
						: "Open Pithos Folder";
323 4ec636f6 Panagiotis Kanavos
			}
324 4ec636f6 Panagiotis Kanavos
		}
325 4ec636f6 Panagiotis Kanavos
326 4ec636f6 Panagiotis Kanavos
		private string _pauseSyncCaption="Pause Synching";
327 4ec636f6 Panagiotis Kanavos
		public string PauseSyncCaption
328 4ec636f6 Panagiotis Kanavos
		{
329 4ec636f6 Panagiotis Kanavos
			get { return _pauseSyncCaption; }
330 4ec636f6 Panagiotis Kanavos
			set
331 4ec636f6 Panagiotis Kanavos
			{
332 4ec636f6 Panagiotis Kanavos
				_pauseSyncCaption = value;
333 4ec636f6 Panagiotis Kanavos
				NotifyOfPropertyChange(() => PauseSyncCaption);
334 4ec636f6 Panagiotis Kanavos
			}
335 4ec636f6 Panagiotis Kanavos
		}
336 4ec636f6 Panagiotis Kanavos
337 4ec636f6 Panagiotis Kanavos
		private readonly ObservableConcurrentCollection<FileEntry> _recentFiles = new ObservableConcurrentCollection<FileEntry>();
338 4ec636f6 Panagiotis Kanavos
		public ObservableConcurrentCollection<FileEntry> RecentFiles
339 4ec636f6 Panagiotis Kanavos
		{
340 4ec636f6 Panagiotis Kanavos
			get { return _recentFiles; }
341 4ec636f6 Panagiotis Kanavos
		}
342 4ec636f6 Panagiotis Kanavos
343 4ec636f6 Panagiotis Kanavos
344 4ec636f6 Panagiotis Kanavos
		private string _statusIcon="../Images/Pithos.ico";
345 4ec636f6 Panagiotis Kanavos
		public string StatusIcon
346 4ec636f6 Panagiotis Kanavos
		{
347 4ec636f6 Panagiotis Kanavos
			get { return _statusIcon; }
348 4ec636f6 Panagiotis Kanavos
			set
349 4ec636f6 Panagiotis Kanavos
			{
350 255f5f86 Panagiotis Kanavos
				//TODO: Ensure all status icons use the Pithos logo
351 4f6d51d4 Panagiotis Kanavos
				_statusIcon = value;
352 4ec636f6 Panagiotis Kanavos
				NotifyOfPropertyChange(() => StatusIcon);
353 4ec636f6 Panagiotis Kanavos
			}
354 4ec636f6 Panagiotis Kanavos
		}
355 4ec636f6 Panagiotis Kanavos
356 4ec636f6 Panagiotis Kanavos
		#endregion
357 4ec636f6 Panagiotis Kanavos
358 4ec636f6 Panagiotis Kanavos
		#region Commands
359 4ec636f6 Panagiotis Kanavos
360 f2d88248 Panagiotis Kanavos
        public void ShowPreferences()
361 f2d88248 Panagiotis Kanavos
        {
362 f2d88248 Panagiotis Kanavos
            ShowPreferences(null);
363 f2d88248 Panagiotis Kanavos
        }
364 f2d88248 Panagiotis Kanavos
365 f2d88248 Panagiotis Kanavos
		public void ShowPreferences(string currentTab)
366 4ec636f6 Panagiotis Kanavos
		{
367 1e26eceb Panagiotis Kanavos
			//Settings.Reload();
368 f2d88248 Panagiotis Kanavos
		    var preferences = new PreferencesViewModel(_windowManager, _events, this, Settings,currentTab);
369 f2d88248 Panagiotis Kanavos
		    _windowManager.ShowDialog(preferences);
370 4ec636f6 Panagiotis Kanavos
			
371 4ec636f6 Panagiotis Kanavos
		}
372 4ec636f6 Panagiotis Kanavos
373 4ec636f6 Panagiotis Kanavos
		public void AboutPithos()
374 4ec636f6 Panagiotis Kanavos
		{
375 4ec636f6 Panagiotis Kanavos
			var about = new AboutViewModel();
376 4ec636f6 Panagiotis Kanavos
			_windowManager.ShowWindow(about);
377 4ec636f6 Panagiotis Kanavos
		}
378 4ec636f6 Panagiotis Kanavos
379 4ec636f6 Panagiotis Kanavos
		public void SendFeedback()
380 4ec636f6 Panagiotis Kanavos
		{
381 4ec636f6 Panagiotis Kanavos
			var feedBack =  IoC.Get<FeedbackViewModel>();
382 4ec636f6 Panagiotis Kanavos
			_windowManager.ShowWindow(feedBack);
383 4ec636f6 Panagiotis Kanavos
		}
384 4ec636f6 Panagiotis Kanavos
385 4ec636f6 Panagiotis Kanavos
		//public PithosCommand OpenPithosFolderCommand { get; private set; }
386 4ec636f6 Panagiotis Kanavos
387 4ec636f6 Panagiotis Kanavos
		public void OpenPithosFolder()
388 4ec636f6 Panagiotis Kanavos
		{
389 4ec636f6 Panagiotis Kanavos
			var account = Settings.Accounts.FirstOrDefault(acc => acc.IsActive);
390 4ec636f6 Panagiotis Kanavos
			if (account == null)
391 4ec636f6 Panagiotis Kanavos
				return;
392 4ec636f6 Panagiotis Kanavos
			Process.Start(account.RootPath);
393 4ec636f6 Panagiotis Kanavos
		}
394 4ec636f6 Panagiotis Kanavos
395 4ec636f6 Panagiotis Kanavos
		public void OpenPithosFolder(AccountInfo account)
396 4ec636f6 Panagiotis Kanavos
		{
397 4ec636f6 Panagiotis Kanavos
			Process.Start(account.AccountPath);
398 4ec636f6 Panagiotis Kanavos
		}
399 4ec636f6 Panagiotis Kanavos
400 4ec636f6 Panagiotis Kanavos
		
401 f734ab5b Panagiotis Kanavos
/*
402 4ec636f6 Panagiotis Kanavos
		public void GoToSite()
403 4ec636f6 Panagiotis Kanavos
		{            
404 4ec636f6 Panagiotis Kanavos
			var site = Properties.Settings.Default.PithosSite;
405 4ec636f6 Panagiotis Kanavos
			Process.Start(site);            
406 4ec636f6 Panagiotis Kanavos
		}
407 f734ab5b Panagiotis Kanavos
*/
408 6aa29f4f Panagiotis Kanavos
409 4ec636f6 Panagiotis Kanavos
		public void GoToSite(AccountInfo account)
410 4ec636f6 Panagiotis Kanavos
		{
411 4ec636f6 Panagiotis Kanavos
			/*var site = String.Format("{0}/ui/?token={1}&user={2}",
412 4ec636f6 Panagiotis Kanavos
				account.SiteUri,account.Token,
413 4ec636f6 Panagiotis Kanavos
				account.UserName);*/
414 4ec636f6 Panagiotis Kanavos
			Process.Start(account.SiteUri);
415 4ec636f6 Panagiotis Kanavos
		}
416 4ec636f6 Panagiotis Kanavos
417 4ec636f6 Panagiotis Kanavos
		public void ShowFileProperties()
418 4ec636f6 Panagiotis Kanavos
		{
419 4ec636f6 Panagiotis Kanavos
			var account = Settings.Accounts.First(acc => acc.IsActive);            
420 4ec636f6 Panagiotis Kanavos
			var dir = new DirectoryInfo(account.RootPath + @"\pithos");
421 4ec636f6 Panagiotis Kanavos
			var files=dir.GetFiles();
422 4ec636f6 Panagiotis Kanavos
			var r=new Random();
423 4ec636f6 Panagiotis Kanavos
			var idx=r.Next(0, files.Length);
424 4ec636f6 Panagiotis Kanavos
			ShowFileProperties(files[idx].FullName);            
425 4ec636f6 Panagiotis Kanavos
		}
426 4ec636f6 Panagiotis Kanavos
427 4ec636f6 Panagiotis Kanavos
		public void ShowFileProperties(string filePath)
428 4ec636f6 Panagiotis Kanavos
		{
429 4ec636f6 Panagiotis Kanavos
			if (String.IsNullOrWhiteSpace(filePath))
430 4ec636f6 Panagiotis Kanavos
				throw new ArgumentNullException("filePath");
431 4f6d51d4 Panagiotis Kanavos
			if (!File.Exists(filePath) && !Directory.Exists(filePath))
432 4ec636f6 Panagiotis Kanavos
				throw new ArgumentException(String.Format("Non existent file {0}",filePath),"filePath");
433 4ec636f6 Panagiotis Kanavos
			Contract.EndContractBlock();
434 4ec636f6 Panagiotis Kanavos
435 4ec636f6 Panagiotis Kanavos
			var pair=(from monitor in  Monitors
436 4ec636f6 Panagiotis Kanavos
							   where filePath.StartsWith(monitor.Value.RootPath, StringComparison.InvariantCultureIgnoreCase)
437 4ec636f6 Panagiotis Kanavos
								   select monitor).FirstOrDefault();
438 255f5f86 Panagiotis Kanavos
			var accountMonitor = pair.Value;
439 4ec636f6 Panagiotis Kanavos
440 4ec636f6 Panagiotis Kanavos
			if (accountMonitor == null)
441 4ec636f6 Panagiotis Kanavos
				return;
442 4ec636f6 Panagiotis Kanavos
443 4ec636f6 Panagiotis Kanavos
			var infoTask=Task.Factory.StartNew(()=>accountMonitor.GetObjectInfo(filePath));
444 4ec636f6 Panagiotis Kanavos
445 4ec636f6 Panagiotis Kanavos
			
446 4ec636f6 Panagiotis Kanavos
447 4ec636f6 Panagiotis Kanavos
			var fileProperties = new FilePropertiesViewModel(this, infoTask,filePath);
448 4ec636f6 Panagiotis Kanavos
			_windowManager.ShowWindow(fileProperties);
449 4ec636f6 Panagiotis Kanavos
		} 
450 4ec636f6 Panagiotis Kanavos
		
451 4ec636f6 Panagiotis Kanavos
		public void ShowContainerProperties()
452 4ec636f6 Panagiotis Kanavos
		{
453 4ec636f6 Panagiotis Kanavos
			var account = Settings.Accounts.First(acc => acc.IsActive);            
454 4ec636f6 Panagiotis Kanavos
			var dir = new DirectoryInfo(account.RootPath);
455 4ec636f6 Panagiotis Kanavos
			var fullName = (from folder in dir.EnumerateDirectories()
456 4ec636f6 Panagiotis Kanavos
							where (folder.Attributes & FileAttributes.Hidden) == 0
457 4ec636f6 Panagiotis Kanavos
							select folder.FullName).First();
458 4ec636f6 Panagiotis Kanavos
			ShowContainerProperties(fullName);            
459 4ec636f6 Panagiotis Kanavos
		}
460 4ec636f6 Panagiotis Kanavos
461 4ec636f6 Panagiotis Kanavos
		public void ShowContainerProperties(string filePath)
462 4ec636f6 Panagiotis Kanavos
		{
463 4ec636f6 Panagiotis Kanavos
			if (String.IsNullOrWhiteSpace(filePath))
464 4ec636f6 Panagiotis Kanavos
				throw new ArgumentNullException("filePath");
465 4ec636f6 Panagiotis Kanavos
			if (!Directory.Exists(filePath))
466 4ec636f6 Panagiotis Kanavos
				throw new ArgumentException(String.Format("Non existent file {0}",filePath),"filePath");
467 4ec636f6 Panagiotis Kanavos
			Contract.EndContractBlock();
468 4ec636f6 Panagiotis Kanavos
469 4ec636f6 Panagiotis Kanavos
			var pair=(from monitor in  Monitors
470 4ec636f6 Panagiotis Kanavos
							   where filePath.StartsWith(monitor.Value.RootPath, StringComparison.InvariantCultureIgnoreCase)
471 4ec636f6 Panagiotis Kanavos
								   select monitor).FirstOrDefault();
472 255f5f86 Panagiotis Kanavos
			var accountMonitor = pair.Value;            
473 4ec636f6 Panagiotis Kanavos
			var info = accountMonitor.GetContainerInfo(filePath);
474 4ec636f6 Panagiotis Kanavos
475 4ec636f6 Panagiotis Kanavos
			
476 4ec636f6 Panagiotis Kanavos
477 4ec636f6 Panagiotis Kanavos
			var containerProperties = new ContainerPropertiesViewModel(this, info,filePath);
478 4ec636f6 Panagiotis Kanavos
			_windowManager.ShowWindow(containerProperties);
479 4ec636f6 Panagiotis Kanavos
		}
480 4ec636f6 Panagiotis Kanavos
481 255f5f86 Panagiotis Kanavos
		public void SynchNow()
482 255f5f86 Panagiotis Kanavos
		{
483 31c97141 Panagiotis Kanavos
			_pollAgent.SynchNow();
484 255f5f86 Panagiotis Kanavos
		}
485 133f83c2 Panagiotis Kanavos
486 4ec636f6 Panagiotis Kanavos
		public ObjectInfo RefreshObjectInfo(ObjectInfo currentInfo)
487 4ec636f6 Panagiotis Kanavos
		{
488 4ec636f6 Panagiotis Kanavos
			if (currentInfo==null)
489 4ec636f6 Panagiotis Kanavos
				throw new ArgumentNullException("currentInfo");
490 4ec636f6 Panagiotis Kanavos
			Contract.EndContractBlock();
491 4ec636f6 Panagiotis Kanavos
492 4ec636f6 Panagiotis Kanavos
			var monitor = Monitors[currentInfo.Account];
493 4ec636f6 Panagiotis Kanavos
			var newInfo=monitor.CloudClient.GetObjectInfo(currentInfo.Account, currentInfo.Container, currentInfo.Name);
494 4ec636f6 Panagiotis Kanavos
			return newInfo;
495 4ec636f6 Panagiotis Kanavos
		}
496 4ec636f6 Panagiotis Kanavos
497 4ec636f6 Panagiotis Kanavos
		public ContainerInfo RefreshContainerInfo(ContainerInfo container)
498 4ec636f6 Panagiotis Kanavos
		{
499 4ec636f6 Panagiotis Kanavos
			if (container == null)
500 4ec636f6 Panagiotis Kanavos
				throw new ArgumentNullException("container");
501 4ec636f6 Panagiotis Kanavos
			Contract.EndContractBlock();
502 4ec636f6 Panagiotis Kanavos
503 4ec636f6 Panagiotis Kanavos
			var monitor = Monitors[container.Account];
504 4ec636f6 Panagiotis Kanavos
			var newInfo = monitor.CloudClient.GetContainerInfo(container.Account, container.Name);
505 4ec636f6 Panagiotis Kanavos
			return newInfo;
506 4ec636f6 Panagiotis Kanavos
		}
507 4ec636f6 Panagiotis Kanavos
508 4ec636f6 Panagiotis Kanavos
509 4ec636f6 Panagiotis Kanavos
		public void ToggleSynching()
510 4ec636f6 Panagiotis Kanavos
		{
511 4ec636f6 Panagiotis Kanavos
			bool isPaused=false;
512 4ec636f6 Panagiotis Kanavos
			foreach (var pair in Monitors)
513 4ec636f6 Panagiotis Kanavos
			{
514 4ec636f6 Panagiotis Kanavos
				var monitor = pair.Value;
515 4ec636f6 Panagiotis Kanavos
				monitor.Pause = !monitor.Pause;
516 4ec636f6 Panagiotis Kanavos
				isPaused = monitor.Pause;
517 4ec636f6 Panagiotis Kanavos
			}
518 4ec636f6 Panagiotis Kanavos
519 4ec636f6 Panagiotis Kanavos
			PauseSyncCaption = isPaused ? "Resume syncing" : "Pause syncing";
520 4ec636f6 Panagiotis Kanavos
			var iconKey = isPaused? "TraySyncPaused" : "TrayInSynch";
521 4ec636f6 Panagiotis Kanavos
			StatusIcon = String.Format(@"../Images/{0}.ico", iconKey);
522 4ec636f6 Panagiotis Kanavos
		}
523 4ec636f6 Panagiotis Kanavos
524 4ec636f6 Panagiotis Kanavos
		public void ExitPithos()
525 4ec636f6 Panagiotis Kanavos
		{
526 4ec636f6 Panagiotis Kanavos
			foreach (var pair in Monitors)
527 4ec636f6 Panagiotis Kanavos
			{
528 4ec636f6 Panagiotis Kanavos
				var monitor = pair.Value;
529 4ec636f6 Panagiotis Kanavos
				monitor.Stop();
530 4ec636f6 Panagiotis Kanavos
			}
531 4ec636f6 Panagiotis Kanavos
532 4ec636f6 Panagiotis Kanavos
			((Window)GetView()).Close();
533 4ec636f6 Panagiotis Kanavos
		}
534 4ec636f6 Panagiotis Kanavos
		#endregion
535 4ec636f6 Panagiotis Kanavos
536 4ec636f6 Panagiotis Kanavos
537 4f6d51d4 Panagiotis Kanavos
		private readonly Dictionary<PithosStatus, StatusInfo> _iconNames = new List<StatusInfo>
538 4ec636f6 Panagiotis Kanavos
			{
539 4ec636f6 Panagiotis Kanavos
				new StatusInfo(PithosStatus.InSynch, "All files up to date", "TrayInSynch"),
540 4ec636f6 Panagiotis Kanavos
				new StatusInfo(PithosStatus.Syncing, "Syncing Files", "TraySynching"),
541 4ec636f6 Panagiotis Kanavos
				new StatusInfo(PithosStatus.SyncPaused, "Sync Paused", "TraySyncPaused")
542 4ec636f6 Panagiotis Kanavos
			}.ToDictionary(s => s.Status);
543 4ec636f6 Panagiotis Kanavos
544 4ec636f6 Panagiotis Kanavos
		readonly IWindowManager _windowManager;
545 255f5f86 Panagiotis Kanavos
		
546 c53aa229 Panagiotis Kanavos
547 cf761c0d Panagiotis Kanavos
		///<summary>
548 cf761c0d Panagiotis Kanavos
		/// Updates the visual status indicators of the application depending on status changes, e.g. icon, stat		
549 cf761c0d Panagiotis Kanavos
		///</summary>
550 4ec636f6 Panagiotis Kanavos
		public void UpdateStatus()
551 4ec636f6 Panagiotis Kanavos
		{
552 4ec636f6 Panagiotis Kanavos
			var pithosStatus = _statusChecker.GetPithosStatus();
553 4ec636f6 Panagiotis Kanavos
554 4f6d51d4 Panagiotis Kanavos
			if (_iconNames.ContainsKey(pithosStatus))
555 4ec636f6 Panagiotis Kanavos
			{
556 4f6d51d4 Panagiotis Kanavos
				var info = _iconNames[pithosStatus];
557 4ec636f6 Panagiotis Kanavos
				StatusIcon = String.Format(@"../Images/{0}.ico", info.IconName);
558 4ec636f6 Panagiotis Kanavos
559 4ec636f6 Panagiotis Kanavos
560 4ec636f6 Panagiotis Kanavos
561 422c9598 Panagiotis Kanavos
				StatusMessage = String.Format("Pithos {0}\r\n{1}", _fileVersion.Value.FileVersion,info.StatusText);
562 4ec636f6 Panagiotis Kanavos
			}
563 4ec636f6 Panagiotis Kanavos
			
564 852d2cf2 Panagiotis Kanavos
			//_events.Publish(new Notification { Title = "Start", Message = "Start Monitoring", Level = TraceLevel.Info});
565 4ec636f6 Panagiotis Kanavos
		}
566 4ec636f6 Panagiotis Kanavos
567 4ec636f6 Panagiotis Kanavos
568 4ec636f6 Panagiotis Kanavos
	   
569 4ec636f6 Panagiotis Kanavos
		private Task StartMonitor(PithosMonitor monitor,int retries=0)
570 4ec636f6 Panagiotis Kanavos
		{
571 4ec636f6 Panagiotis Kanavos
			return Task.Factory.StartNew(() =>
572 4ec636f6 Panagiotis Kanavos
			{
573 4ec636f6 Panagiotis Kanavos
				using (log4net.ThreadContext.Stacks["Monitor"].Push("Start"))
574 4ec636f6 Panagiotis Kanavos
				{
575 4ec636f6 Panagiotis Kanavos
					try
576 4ec636f6 Panagiotis Kanavos
					{
577 4ec636f6 Panagiotis Kanavos
						Log.InfoFormat("Start Monitoring {0}", monitor.UserName);
578 4ec636f6 Panagiotis Kanavos
579 4ec636f6 Panagiotis Kanavos
						monitor.Start();
580 4ec636f6 Panagiotis Kanavos
					}
581 4ec636f6 Panagiotis Kanavos
					catch (WebException exc)
582 4ec636f6 Panagiotis Kanavos
					{
583 4ec636f6 Panagiotis Kanavos
						if (AbandonRetry(monitor, retries))
584 4ec636f6 Panagiotis Kanavos
							return;
585 4ec636f6 Panagiotis Kanavos
586 255f5f86 Panagiotis Kanavos
						HttpStatusCode statusCode =HttpStatusCode.OK;
587 255f5f86 Panagiotis Kanavos
						var response = exc.Response as HttpWebResponse;
588 255f5f86 Panagiotis Kanavos
						if(response!=null)
589 255f5f86 Panagiotis Kanavos
							statusCode = response.StatusCode;
590 255f5f86 Panagiotis Kanavos
591 255f5f86 Panagiotis Kanavos
						switch (statusCode)
592 255f5f86 Panagiotis Kanavos
						{
593 255f5f86 Panagiotis Kanavos
							case HttpStatusCode.Unauthorized:
594 255f5f86 Panagiotis Kanavos
								var message = String.Format("API Key Expired for {0}. Starting Renewal",
595 255f5f86 Panagiotis Kanavos
															monitor.UserName);
596 255f5f86 Panagiotis Kanavos
								Log.Error(message, exc);
597 1e26eceb Panagiotis Kanavos
						        var account = Settings.Accounts.Find(acc => acc.AccountName == monitor.UserName);                                
598 1e26eceb Panagiotis Kanavos
						        account.IsExpired = true;
599 1e26eceb Panagiotis Kanavos
                                Notify(new ExpirationNotification(account));
600 1e26eceb Panagiotis Kanavos
								//TryAuthorize(monitor.UserName, retries).Wait();
601 255f5f86 Panagiotis Kanavos
								break;
602 255f5f86 Panagiotis Kanavos
							case HttpStatusCode.ProxyAuthenticationRequired:
603 255f5f86 Panagiotis Kanavos
								TryAuthenticateProxy(monitor,retries);
604 255f5f86 Panagiotis Kanavos
								break;
605 255f5f86 Panagiotis Kanavos
							default:
606 255f5f86 Panagiotis Kanavos
								TryLater(monitor, exc, retries);
607 255f5f86 Panagiotis Kanavos
								break;
608 255f5f86 Panagiotis Kanavos
						}
609 4ec636f6 Panagiotis Kanavos
					}
610 4ec636f6 Panagiotis Kanavos
					catch (Exception exc)
611 4ec636f6 Panagiotis Kanavos
					{
612 4ec636f6 Panagiotis Kanavos
						if (AbandonRetry(monitor, retries)) 
613 4ec636f6 Panagiotis Kanavos
							return;
614 4ec636f6 Panagiotis Kanavos
615 4ec636f6 Panagiotis Kanavos
						TryLater(monitor,exc,retries);
616 4ec636f6 Panagiotis Kanavos
					}
617 4ec636f6 Panagiotis Kanavos
				}
618 4ec636f6 Panagiotis Kanavos
			});
619 4ec636f6 Panagiotis Kanavos
		}
620 4ec636f6 Panagiotis Kanavos
621 255f5f86 Panagiotis Kanavos
		private void TryAuthenticateProxy(PithosMonitor monitor,int retries)
622 255f5f86 Panagiotis Kanavos
		{
623 255f5f86 Panagiotis Kanavos
			Execute.OnUIThread(() =>
624 255f5f86 Panagiotis Kanavos
								   {                                       
625 255f5f86 Panagiotis Kanavos
									   var proxyAccount = IoC.Get<ProxyAccountViewModel>();
626 255f5f86 Panagiotis Kanavos
										proxyAccount.Settings = this.Settings;
627 255f5f86 Panagiotis Kanavos
									   if (true != _windowManager.ShowDialog(proxyAccount)) 
628 255f5f86 Panagiotis Kanavos
										   return;
629 255f5f86 Panagiotis Kanavos
									   StartMonitor(monitor, retries);
630 255f5f86 Panagiotis Kanavos
									   NotifyOfPropertyChange(() => Accounts);
631 255f5f86 Panagiotis Kanavos
								   });
632 255f5f86 Panagiotis Kanavos
		}
633 65282d58 Panagiotis Kanavos
634 255f5f86 Panagiotis Kanavos
		private bool AbandonRetry(PithosMonitor monitor, int retries)
635 4ec636f6 Panagiotis Kanavos
		{
636 4ec636f6 Panagiotis Kanavos
			if (retries > 1)
637 4ec636f6 Panagiotis Kanavos
			{
638 4ec636f6 Panagiotis Kanavos
				var message = String.Format("Monitoring of account {0} has failed too many times. Will not retry",
639 4ec636f6 Panagiotis Kanavos
											monitor.UserName);
640 4ec636f6 Panagiotis Kanavos
				_events.Publish(new Notification
641 4ec636f6 Panagiotis Kanavos
									{Title = "Account monitoring failed", Message = message, Level = TraceLevel.Error});
642 4ec636f6 Panagiotis Kanavos
				return true;
643 4ec636f6 Panagiotis Kanavos
			}
644 4ec636f6 Panagiotis Kanavos
			return false;
645 4ec636f6 Panagiotis Kanavos
		}
646 4ec636f6 Panagiotis Kanavos
647 4ec636f6 Panagiotis Kanavos
648 4ec636f6 Panagiotis Kanavos
649 4ec636f6 Panagiotis Kanavos
		private static bool IsUnauthorized(WebException exc)
650 4ec636f6 Panagiotis Kanavos
		{
651 4ec636f6 Panagiotis Kanavos
			if (exc==null)
652 4ec636f6 Panagiotis Kanavos
				throw new ArgumentNullException("exc");
653 4ec636f6 Panagiotis Kanavos
			Contract.EndContractBlock();
654 4ec636f6 Panagiotis Kanavos
655 4ec636f6 Panagiotis Kanavos
			var response = exc.Response as HttpWebResponse;
656 4ec636f6 Panagiotis Kanavos
			if (response == null)
657 4ec636f6 Panagiotis Kanavos
				return false;
658 4ec636f6 Panagiotis Kanavos
			return (response.StatusCode == HttpStatusCode.Unauthorized);
659 4ec636f6 Panagiotis Kanavos
		}
660 4ec636f6 Panagiotis Kanavos
661 4ec636f6 Panagiotis Kanavos
		private void TryLater(PithosMonitor monitor, Exception exc,int retries)
662 4ec636f6 Panagiotis Kanavos
		{
663 4ec636f6 Panagiotis Kanavos
			var message = String.Format("An exception occured. Can't start monitoring\nWill retry in 10 seconds");
664 4ec636f6 Panagiotis Kanavos
			Task.Factory.StartNewDelayed(10000, () => StartMonitor(monitor,retries+1));
665 4ec636f6 Panagiotis Kanavos
			_events.Publish(new Notification
666 4ec636f6 Panagiotis Kanavos
								{Title = "Error", Message = message, Level = TraceLevel.Error});
667 4ec636f6 Panagiotis Kanavos
			Log.Error(message, exc);
668 4ec636f6 Panagiotis Kanavos
		}
669 4ec636f6 Panagiotis Kanavos
670 4ec636f6 Panagiotis Kanavos
671 4ec636f6 Panagiotis Kanavos
		public void NotifyChange(string status, TraceLevel level=TraceLevel.Info)
672 4ec636f6 Panagiotis Kanavos
		{
673 4f6d51d4 Panagiotis Kanavos
			StatusMessage = status;
674 4ec636f6 Panagiotis Kanavos
			
675 4ec636f6 Panagiotis Kanavos
			_events.Publish(new Notification { Title = "Pithos", Message = status, Level = level });
676 4ec636f6 Panagiotis Kanavos
		}
677 4ec636f6 Panagiotis Kanavos
678 4ec636f6 Panagiotis Kanavos
		public void NotifyChangedFile(string filePath)
679 4ec636f6 Panagiotis Kanavos
		{
680 4ec636f6 Panagiotis Kanavos
			var entry = new FileEntry {FullPath=filePath};
681 4f6d51d4 Panagiotis Kanavos
			IProducerConsumerCollection<FileEntry> files=RecentFiles;
682 4ec636f6 Panagiotis Kanavos
			FileEntry popped;
683 4ec636f6 Panagiotis Kanavos
			while (files.Count > 5)
684 4ec636f6 Panagiotis Kanavos
				files.TryTake(out popped);
685 4ec636f6 Panagiotis Kanavos
			files.TryAdd(entry);
686 4ec636f6 Panagiotis Kanavos
		}
687 4ec636f6 Panagiotis Kanavos
688 4ec636f6 Panagiotis Kanavos
		public void NotifyAccount(AccountInfo account)
689 4ec636f6 Panagiotis Kanavos
		{
690 4ec636f6 Panagiotis Kanavos
			if (account== null)
691 4ec636f6 Panagiotis Kanavos
				return;
692 4ec636f6 Panagiotis Kanavos
			//TODO: What happens to an existing account whose Token has changed?
693 4ec636f6 Panagiotis Kanavos
			account.SiteUri= String.Format("{0}/ui/?token={1}&user={2}",
694 eae84ae8 Panagiotis Kanavos
				account.SiteUri, Uri.EscapeDataString(account.Token),
695 255f5f86 Panagiotis Kanavos
				Uri.EscapeDataString(account.UserName));
696 4ec636f6 Panagiotis Kanavos
697 4ec636f6 Panagiotis Kanavos
			if (Accounts.All(item => item.UserName != account.UserName))
698 4ec636f6 Panagiotis Kanavos
				Accounts.TryAdd(account);
699 4ec636f6 Panagiotis Kanavos
700 4ec636f6 Panagiotis Kanavos
		}
701 4ec636f6 Panagiotis Kanavos
702 255f5f86 Panagiotis Kanavos
		public void NotifyConflicts(IEnumerable<FileSystemInfo> conflictFiles, string message)
703 255f5f86 Panagiotis Kanavos
		{
704 255f5f86 Panagiotis Kanavos
			if (conflictFiles == null)
705 255f5f86 Panagiotis Kanavos
				return;
706 255f5f86 Panagiotis Kanavos
			if (!conflictFiles.Any())
707 255f5f86 Panagiotis Kanavos
				return;
708 e5b65606 Panagiotis Kanavos
709 255f5f86 Panagiotis Kanavos
			UpdateStatus();
710 255f5f86 Panagiotis Kanavos
			//TODO: Create a more specific message. For now, just show a warning
711 255f5f86 Panagiotis Kanavos
			NotifyForFiles(conflictFiles,message,TraceLevel.Warning);
712 9c6d3193 Panagiotis Kanavos
713 255f5f86 Panagiotis Kanavos
		}
714 9c6d3193 Panagiotis Kanavos
715 255f5f86 Panagiotis Kanavos
		public void NotifyForFiles(IEnumerable<FileSystemInfo> files, string message,TraceLevel level=TraceLevel.Info)
716 255f5f86 Panagiotis Kanavos
		{
717 255f5f86 Panagiotis Kanavos
			if (files == null)
718 255f5f86 Panagiotis Kanavos
				return;
719 255f5f86 Panagiotis Kanavos
			if (!files.Any())
720 255f5f86 Panagiotis Kanavos
				return;
721 9c6d3193 Panagiotis Kanavos
722 255f5f86 Panagiotis Kanavos
			StatusMessage = message;
723 9c6d3193 Panagiotis Kanavos
724 255f5f86 Panagiotis Kanavos
			_events.Publish(new Notification { Title = "Pithos", Message = message, Level = level});
725 255f5f86 Panagiotis Kanavos
		}
726 9c6d3193 Panagiotis Kanavos
727 255f5f86 Panagiotis Kanavos
		public void Notify(Notification notification)
728 255f5f86 Panagiotis Kanavos
		{
729 255f5f86 Panagiotis Kanavos
			_events.Publish(notification);
730 255f5f86 Panagiotis Kanavos
		}
731 e5b65606 Panagiotis Kanavos
732 4ec636f6 Panagiotis Kanavos
733 255f5f86 Panagiotis Kanavos
		public void RemoveMonitor(string accountName)
734 4ec636f6 Panagiotis Kanavos
		{
735 4ec636f6 Panagiotis Kanavos
			if (String.IsNullOrWhiteSpace(accountName))
736 4ec636f6 Panagiotis Kanavos
				return;
737 4ec636f6 Panagiotis Kanavos
738 4ec636f6 Panagiotis Kanavos
			var accountInfo=_accounts.FirstOrDefault(account => account.UserName == accountName);
739 4ec636f6 Panagiotis Kanavos
			_accounts.TryRemove(accountInfo);
740 4ec636f6 Panagiotis Kanavos
741 ec1a1baf Panagiotis Kanavos
		    _pollAgent.RemoveAccount(accountInfo);
742 4ec636f6 Panagiotis Kanavos
			PithosMonitor monitor;
743 4ec636f6 Panagiotis Kanavos
			if (Monitors.TryRemove(accountName, out monitor))
744 4ec636f6 Panagiotis Kanavos
			{
745 4ec636f6 Panagiotis Kanavos
				monitor.Stop();
746 4ec636f6 Panagiotis Kanavos
			}
747 4ec636f6 Panagiotis Kanavos
		}
748 4ec636f6 Panagiotis Kanavos
749 4ec636f6 Panagiotis Kanavos
		public void RefreshOverlays()
750 4ec636f6 Panagiotis Kanavos
		{
751 4ec636f6 Panagiotis Kanavos
			foreach (var pair in Monitors)
752 4ec636f6 Panagiotis Kanavos
			{
753 4ec636f6 Panagiotis Kanavos
				var monitor = pair.Value;
754 4ec636f6 Panagiotis Kanavos
755 4ec636f6 Panagiotis Kanavos
				var path = monitor.RootPath;
756 4ec636f6 Panagiotis Kanavos
757 4ec636f6 Panagiotis Kanavos
				if (String.IsNullOrWhiteSpace(path))
758 4ec636f6 Panagiotis Kanavos
					continue;
759 4ec636f6 Panagiotis Kanavos
760 4ec636f6 Panagiotis Kanavos
				if (!Directory.Exists(path) && !File.Exists(path))
761 4ec636f6 Panagiotis Kanavos
					continue;
762 4ec636f6 Panagiotis Kanavos
763 4ec636f6 Panagiotis Kanavos
				IntPtr pathPointer = Marshal.StringToCoTaskMemAuto(path);
764 4ec636f6 Panagiotis Kanavos
765 4ec636f6 Panagiotis Kanavos
				try
766 4ec636f6 Panagiotis Kanavos
				{
767 4ec636f6 Panagiotis Kanavos
					NativeMethods.SHChangeNotify(HChangeNotifyEventID.SHCNE_UPDATEITEM,
768 4ec636f6 Panagiotis Kanavos
												 HChangeNotifyFlags.SHCNF_PATHW | HChangeNotifyFlags.SHCNF_FLUSHNOWAIT,
769 4ec636f6 Panagiotis Kanavos
												 pathPointer, IntPtr.Zero);
770 4ec636f6 Panagiotis Kanavos
				}
771 4ec636f6 Panagiotis Kanavos
				finally
772 4ec636f6 Panagiotis Kanavos
				{
773 4ec636f6 Panagiotis Kanavos
					Marshal.FreeHGlobal(pathPointer);
774 4ec636f6 Panagiotis Kanavos
				}
775 4ec636f6 Panagiotis Kanavos
			}
776 4ec636f6 Panagiotis Kanavos
		}
777 4ec636f6 Panagiotis Kanavos
778 4ec636f6 Panagiotis Kanavos
		#region Event Handlers
779 4ec636f6 Panagiotis Kanavos
		
780 4ec636f6 Panagiotis Kanavos
		public void Handle(SelectiveSynchChanges message)
781 4ec636f6 Panagiotis Kanavos
		{
782 4ec636f6 Panagiotis Kanavos
			var accountName = message.Account.AccountName;
783 4ec636f6 Panagiotis Kanavos
			PithosMonitor monitor;
784 4ec636f6 Panagiotis Kanavos
			if (_monitors.TryGetValue(accountName, out monitor))
785 4ec636f6 Panagiotis Kanavos
			{
786 759bd3c4 Panagiotis Kanavos
				monitor.SetSelectivePaths(message.Uris,message.Added,message.Removed);
787 4ec636f6 Panagiotis Kanavos
788 4ec636f6 Panagiotis Kanavos
			}
789 4ec636f6 Panagiotis Kanavos
			
790 4ec636f6 Panagiotis Kanavos
		}
791 4ec636f6 Panagiotis Kanavos
792 4ec636f6 Panagiotis Kanavos
793 255f5f86 Panagiotis Kanavos
		private bool _pollStarted = false;
794 eae84ae8 Panagiotis Kanavos
795 255f5f86 Panagiotis Kanavos
		//SMELL: Doing so much work for notifications in the shell is wrong
796 255f5f86 Panagiotis Kanavos
		//The notifications should be moved to their own view/viewmodel pair
797 255f5f86 Panagiotis Kanavos
		//and different templates should be used for different message types
798 255f5f86 Panagiotis Kanavos
		//This will also allow the addition of extra functionality, eg. actions
799 255f5f86 Panagiotis Kanavos
		//
800 4ec636f6 Panagiotis Kanavos
		public void Handle(Notification notification)
801 4ec636f6 Panagiotis Kanavos
		{
802 255f5f86 Panagiotis Kanavos
			UpdateStatus();
803 e5b65606 Panagiotis Kanavos
804 4ec636f6 Panagiotis Kanavos
			if (!Settings.ShowDesktopNotifications)
805 4ec636f6 Panagiotis Kanavos
				return;
806 eae84ae8 Panagiotis Kanavos
807 255f5f86 Panagiotis Kanavos
			if (notification is PollNotification)
808 255f5f86 Panagiotis Kanavos
			{
809 255f5f86 Panagiotis Kanavos
				_pollStarted = true;
810 255f5f86 Panagiotis Kanavos
				return;
811 255f5f86 Panagiotis Kanavos
			}
812 255f5f86 Panagiotis Kanavos
			if (notification is CloudNotification)
813 255f5f86 Panagiotis Kanavos
			{
814 255f5f86 Panagiotis Kanavos
				if (!_pollStarted) 
815 255f5f86 Panagiotis Kanavos
					return;
816 255f5f86 Panagiotis Kanavos
				_pollStarted= false;
817 255f5f86 Panagiotis Kanavos
				notification.Title = "Pithos";
818 255f5f86 Panagiotis Kanavos
				notification.Message = "Start Synchronisation";
819 255f5f86 Panagiotis Kanavos
			}
820 255f5f86 Panagiotis Kanavos
821 255f5f86 Panagiotis Kanavos
			if (String.IsNullOrWhiteSpace(notification.Message) && String.IsNullOrWhiteSpace(notification.Title))
822 255f5f86 Panagiotis Kanavos
				return;
823 2dc6f765 Panagiotis Kanavos
824 4f6d51d4 Panagiotis Kanavos
			BalloonIcon icon;
825 4ec636f6 Panagiotis Kanavos
			switch (notification.Level)
826 4ec636f6 Panagiotis Kanavos
			{
827 4ec636f6 Panagiotis Kanavos
				case TraceLevel.Error:
828 4ec636f6 Panagiotis Kanavos
					icon = BalloonIcon.Error;
829 4ec636f6 Panagiotis Kanavos
					break;
830 4ec636f6 Panagiotis Kanavos
				case TraceLevel.Info:
831 4ec636f6 Panagiotis Kanavos
				case TraceLevel.Verbose:
832 4ec636f6 Panagiotis Kanavos
					icon = BalloonIcon.Info;
833 4ec636f6 Panagiotis Kanavos
					break;
834 4ec636f6 Panagiotis Kanavos
				case TraceLevel.Warning:
835 4ec636f6 Panagiotis Kanavos
					icon = BalloonIcon.Warning;
836 4ec636f6 Panagiotis Kanavos
					break;
837 4ec636f6 Panagiotis Kanavos
				default:
838 4ec636f6 Panagiotis Kanavos
					icon = BalloonIcon.None;
839 4ec636f6 Panagiotis Kanavos
					break;
840 4ec636f6 Panagiotis Kanavos
			}
841 255f5f86 Panagiotis Kanavos
			
842 4ec636f6 Panagiotis Kanavos
			if (Settings.ShowDesktopNotifications)
843 4ec636f6 Panagiotis Kanavos
			{
844 f2d88248 Panagiotis Kanavos
				var tv = (ShellView) GetView();
845 f2d88248 Panagiotis Kanavos
			    System.Action clickAction = null;
846 f2d88248 Panagiotis Kanavos
                if (notification is ExpirationNotification)
847 f2d88248 Panagiotis Kanavos
                {
848 f2d88248 Panagiotis Kanavos
                    clickAction = ()=>ShowPreferences("AccountTab");
849 f2d88248 Panagiotis Kanavos
                }
850 f2d88248 Panagiotis Kanavos
				var balloon=new PithosBalloon{Title=notification.Title,Message=notification.Message,Icon=icon,ClickAction=clickAction};
851 255f5f86 Panagiotis Kanavos
				tv.TaskbarView.ShowCustomBalloon(balloon,PopupAnimation.Fade,4000);
852 fb9d6e00 Panagiotis Kanavos
//				tv.TaskbarView.ShowBalloonTip(notification.Title, notification.Message, icon);
853 4ec636f6 Panagiotis Kanavos
			}
854 4ec636f6 Panagiotis Kanavos
		}
855 4ec636f6 Panagiotis Kanavos
		#endregion
856 4ec636f6 Panagiotis Kanavos
857 4ec636f6 Panagiotis Kanavos
		public void Handle(ShowFilePropertiesEvent message)
858 4ec636f6 Panagiotis Kanavos
		{
859 4ec636f6 Panagiotis Kanavos
			if (message == null)
860 4ec636f6 Panagiotis Kanavos
				throw new ArgumentNullException("message");
861 4ec636f6 Panagiotis Kanavos
			if (String.IsNullOrWhiteSpace(message.FileName) )
862 4ec636f6 Panagiotis Kanavos
				throw new ArgumentException("message");
863 4ec636f6 Panagiotis Kanavos
			Contract.EndContractBlock();
864 4ec636f6 Panagiotis Kanavos
865 4ec636f6 Panagiotis Kanavos
			var fileName = message.FileName;
866 255f5f86 Panagiotis Kanavos
			//TODO: Display file properties for non-container folders
867 4ec636f6 Panagiotis Kanavos
			if (File.Exists(fileName))
868 255f5f86 Panagiotis Kanavos
				//Retrieve the full name with exact casing. Pithos names are case sensitive				
869 255f5f86 Panagiotis Kanavos
				ShowFileProperties(FileInfoExtensions.GetProperFilePathCapitalization(fileName));
870 4ec636f6 Panagiotis Kanavos
			else if (Directory.Exists(fileName))
871 255f5f86 Panagiotis Kanavos
				//Retrieve the full name with exact casing. Pithos names are case sensitive
872 4f6d51d4 Panagiotis Kanavos
			{
873 255f5f86 Panagiotis Kanavos
				var path = FileInfoExtensions.GetProperDirectoryCapitalization(fileName);
874 255f5f86 Panagiotis Kanavos
				if (IsContainer(path))
875 255f5f86 Panagiotis Kanavos
					ShowContainerProperties(path);
876 255f5f86 Panagiotis Kanavos
				else
877 255f5f86 Panagiotis Kanavos
					ShowFileProperties(path);
878 4f6d51d4 Panagiotis Kanavos
			}
879 4ec636f6 Panagiotis Kanavos
		}
880 4f6d51d4 Panagiotis Kanavos
881 255f5f86 Panagiotis Kanavos
		private bool IsContainer(string path)
882 255f5f86 Panagiotis Kanavos
		{
883 255f5f86 Panagiotis Kanavos
			var matchingFolders = from account in _accounts
884 255f5f86 Panagiotis Kanavos
								  from rootFolder in Directory.GetDirectories(account.AccountPath)
885 255f5f86 Panagiotis Kanavos
								  where rootFolder.Equals(path, StringComparison.InvariantCultureIgnoreCase)
886 255f5f86 Panagiotis Kanavos
								  select rootFolder;
887 255f5f86 Panagiotis Kanavos
			return matchingFolders.Any();
888 255f5f86 Panagiotis Kanavos
		}
889 255f5f86 Panagiotis Kanavos
890 255f5f86 Panagiotis Kanavos
		public FileStatus GetFileStatus(string localFileName)
891 255f5f86 Panagiotis Kanavos
		{
892 255f5f86 Panagiotis Kanavos
			if (String.IsNullOrWhiteSpace(localFileName))
893 255f5f86 Panagiotis Kanavos
				throw new ArgumentNullException("localFileName");
894 255f5f86 Panagiotis Kanavos
			Contract.EndContractBlock();
895 255f5f86 Panagiotis Kanavos
			
896 255f5f86 Panagiotis Kanavos
			var statusKeeper = IoC.Get<IStatusKeeper>();
897 255f5f86 Panagiotis Kanavos
			var status=statusKeeper.GetFileStatus(localFileName);
898 255f5f86 Panagiotis Kanavos
			return status;
899 255f5f86 Panagiotis Kanavos
		}
900 4ec636f6 Panagiotis Kanavos
	}
901 9bae55d1 Panagiotis Kanavos
}