Added action to the PithosBalloon
[pithos-ms-client] / trunk / Pithos.Client.WPF / Preferences / PreferencesViewModel.cs
1 #region
2 /* -----------------------------------------------------------------------
3  * <copyright file="PreferencesViewModel.cs" company="GRNet">
4  * 
5  * Copyright 2011-2012 GRNET S.A. All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or
8  * without modification, are permitted provided that the following
9  * conditions are met:
10  *
11  *   1. Redistributions of source code must retain the above
12  *      copyright notice, this list of conditions and the following
13  *      disclaimer.
14  *
15  *   2. Redistributions in binary form must reproduce the above
16  *      copyright notice, this list of conditions and the following
17  *      disclaimer in the documentation and/or other materials
18  *      provided with the distribution.
19  *
20  *
21  * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
22  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
25  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
28  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  * The views and conclusions contained in the software and
35  * documentation are those of the authors and should not be
36  * interpreted as representing official policies, either expressed
37  * or implied, of GRNET S.A.
38  * </copyright>
39  * -----------------------------------------------------------------------
40  */
41 #endregion
42
43 // </copyright>
44 // -----------------------------------------------------------------------
45
46 using System.Collections.Concurrent;
47 using System.ComponentModel.Composition;
48 using System.IO;
49 using System.Net;
50 using System.Threading.Tasks;
51 using System.Windows;
52 using System.Windows.Forms;
53 using Caliburn.Micro;
54 using Pithos.Client.WPF.Configuration;
55 using Pithos.Client.WPF.SelectiveSynch;
56 using Pithos.Core;
57 using Pithos.Interfaces;
58 using System;
59 using System.Linq;
60 using Screen = Caliburn.Micro.Screen;
61
62 namespace Pithos.Client.WPF.Preferences
63 {
64     /// <summary>
65     /// TODO: Update summary.
66     /// </summary>
67     [Export]
68     public class PreferencesViewModel : Screen
69     {
70         private IEventAggregator _events;
71
72
73         private PithosSettings _settings;
74         public PithosSettings Settings
75         {
76             get { return _settings; }
77             set
78             {
79                 _settings = value;
80                 NotifyOfPropertyChange(()=>Settings);
81             }
82         }
83
84         private ObservableConcurrentCollection<AccountSettings> _accounts;
85         public ObservableConcurrentCollection<AccountSettings> Accounts
86         {
87             get { return _accounts; }
88             set 
89             { 
90                 _accounts = value;
91                 NotifyOfPropertyChange(()=>Accounts);
92             }
93         }
94         
95         public bool StartOnSystemStartup { get; set; }
96
97         public ShellViewModel Shell { get;  set; }
98         //ShellExtensionController _extensionController=new ShellExtensionController();
99
100         public PreferencesViewModel(IWindowManager windowManager, IEventAggregator events, ShellViewModel shell, PithosSettings settings, string currentTab)
101         {
102             _windowManager = windowManager;
103             _events = events;
104
105             DisplayName = "Pithos Preferences";
106             Shell = shell;
107             
108             Settings=settings;
109             Accounts = new ObservableConcurrentCollection<AccountSettings>();
110             if (settings.Accounts == null)
111             {
112                 settings.Accounts=new AccountsCollection();
113                 settings.Save();
114             }
115             Accounts.AddFromEnumerable(settings.Accounts);
116             
117             var startupPath = Environment.GetFolderPath(Environment.SpecialFolder.Startup);
118             _shortcutPath = Path.Combine(startupPath, "Pithos.lnk");
119
120
121             StartOnSystemStartup = File.Exists(_shortcutPath);
122
123             SelectedTab = currentTab;
124         }
125
126         private string _selectedTab="General";
127         public string SelectedTab
128         {
129             get { return _selectedTab; }
130             set
131             {
132                 _selectedTab = value??"General";
133                 NotifyOfPropertyChange(()=>SelectedTab);
134                 NotifyOfPropertyChange(() => AccountTabSelected);
135             }
136         }
137
138
139         public bool AccountTabSelected
140         {
141             get { return _selectedTab == "AccountTab"; }
142         }
143         #region Preferences Properties
144
145         private bool _noProxy;
146         public bool NoProxy
147         {
148             get { return _noProxy; }
149             set
150             {
151                 _noProxy = value;
152                 NotifyOfPropertyChange(()=>NoProxy);
153             }
154         }
155
156
157         private bool _defaultProxy;
158
159         public bool DefaultProxy
160         {
161             get { return _defaultProxy; }
162             set
163             {
164                 _defaultProxy = value;
165                 NotifyOfPropertyChange(() => DefaultProxy);
166             }
167         }
168
169
170         private bool _manualProxy;
171
172         public bool ManualProxy
173         {
174             get { return _manualProxy; }
175             set
176             {
177                 _manualProxy = value;
178                 NotifyOfPropertyChange(() => ManualProxy);
179             }
180         }
181         #endregion
182
183
184         public int StartupDelay
185         {
186             get { return (int) Settings.StartupDelay.TotalMinutes; }
187             set
188             {
189                 if (value<0)
190                     throw new ArgumentOutOfRangeException("value","The Startup Delay must be greater or equal to 0");
191                 Settings.StartupDelay = TimeSpan.FromMinutes(value);
192                 NotifyOfPropertyChange(()=>StartupDelay);
193             }
194         }
195        
196         #region Commands
197         
198         public bool CanSelectiveSyncFolders
199         {
200             get { return CurrentAccount != null; }
201         }
202
203         public void SelectiveSyncFolders()
204         {
205             var monitor = Shell.Monitors[CurrentAccount.AccountName];
206             
207
208             var model = new SelectiveSynchViewModel(monitor,_events,CurrentAccount);
209             if (_windowManager.ShowDialog(model) == true)
210             {
211                 
212             }
213         }
214
215         public async Task RefreshApiKey()
216         {            
217             await Shell.TryAuthorize(CurrentAccount.AccountName, 3);
218             NotifyOfPropertyChange(()=>CurrentAccount);
219         }
220     
221         public void SaveChanges()
222         {
223             DoSave();
224             TryClose(true);
225         }
226
227         public void RejectChanges()
228         {
229             Settings.Reload();
230             TryClose(false);
231         }
232
233         public void ApplyChanges()
234         {
235             DoSave();
236         }
237
238         private void DoSave()
239         {
240             Settings.Save();
241             //SetStartupMode();            
242
243             foreach (var account in Settings.Accounts)
244             {                                
245                 Shell.MonitorAccount(account);
246             }
247
248             NotifyOfPropertyChange(()=>Settings);
249         }
250
251      /*   public void ChangePithosFolder()
252         {
253             var browser = new FolderBrowserDialog();
254             browser.SelectedPath = Settings.PithosPath;
255             var result = browser.ShowDialog((IWin32Window)GetView());
256             if (result == DialogResult.OK)
257             {
258                 var newPath = browser.SelectedPath;
259                 var accountName = CurrentAccount.AccountName;
260                 var monitor = Shell.Monitors[accountName];
261                 monitor.Stop();
262                 
263                 Shell.Monitors.Remove(accountName);
264
265                 Directory.Move(Settings.PithosPath, newPath);
266                 Settings.PithosPath = newPath;
267                 Settings.Save();
268
269                 Shell.MonitorAccount(CurrentAccount);
270
271                 NotifyOfPropertyChange(() => Settings);                
272             }
273         }
274 */
275
276         
277
278        public void AddAccount()
279        {
280            var wizard = new AddAccountViewModel();
281            if (_windowManager.ShowDialog(wizard) == true)
282            {
283                string selectedPath = wizard.AccountPath;
284                var initialRootPath = Path.Combine(selectedPath, "Okeanos");
285                var actualRootPath= initialRootPath;
286                int attempt = 1;
287                while (Directory.Exists(actualRootPath) || File.Exists(actualRootPath))
288                {
289                    actualRootPath = String.Format("{0} {1}", initialRootPath,attempt++);
290                }
291
292                var newAccount = new AccountSettings
293                                     {
294                                         AccountName = wizard.AccountName,
295                                         ServerUrl=wizard.CurrentServer,
296                                         ApiKey=wizard.Token,
297                                         RootPath = actualRootPath,
298                                         IsActive=wizard.IsAccountActive
299                                     };
300                Settings.Accounts.Add(newAccount);
301                (Accounts as IProducerConsumerCollection<AccountSettings>).TryAdd(newAccount);
302                CurrentAccount = newAccount;
303                NotifyOfPropertyChange(() => Accounts);
304                NotifyOfPropertyChange(() => Settings);   
305            }
306
307
308             
309        }
310
311         public async void AddPithosAccount()
312        {
313             var credentials=await PithosAccount.RetrieveCredentials(Settings.PithosLoginUrl);
314             var account = Settings.Accounts.FirstOrDefault(act => act.AccountName == credentials.UserName);
315             if (account == null)
316             {
317                 account=new AccountSettings{
318                     AccountName=credentials.UserName,
319                     ApiKey=credentials.Password
320                 };
321                 Settings.Accounts.Add(account);
322                 (Accounts as IProducerConsumerCollection<AccountSettings>).TryAdd(account);
323             }
324             else
325             {
326                 account.ApiKey=credentials.Password;
327             }
328             //SelectedAccountIndex= Settings.Accounts.IndexOf(account);
329             CurrentAccount = account;
330             NotifyOfPropertyChange(() => Accounts);
331             NotifyOfPropertyChange(()=>Settings);                       
332        }
333
334         public void RemoveAccount()
335         {
336             var accountName = CurrentAccount.AccountName;
337             Settings.Accounts.Remove(CurrentAccount);
338
339             Accounts.TryRemove(CurrentAccount);
340             
341             
342             CurrentAccount = null;
343             //Accounts = Settings.Accounts;
344             //Settings.Save();            
345             Shell.RemoveMonitor(accountName);
346             NotifyOfPropertyChange(() => Accounts);
347             NotifyOfPropertyChange(() => Settings);                       
348             
349             //NotifyOfPropertyChange("Settings.Accounts");
350         }
351
352         public bool CanRemoveAccount
353         {
354             get { return (CurrentAccount != null); }
355         }
356
357
358
359         public bool ExtensionsActivated
360         {
361             get { return Settings.ExtensionsActivated; }
362             set
363             {
364                 if (Settings.ExtensionsActivated == value)
365                     return;
366
367                 Settings.ExtensionsActivated = value;
368
369 /*
370                 if (value)
371                     _extensionController.RegisterExtensions();
372                 else
373                 {
374                     _extensionController.UnregisterExtensions();
375                 }
376 */
377                 NotifyOfPropertyChange(() => ExtensionsActivated);
378             }
379         }
380
381        
382         #endregion
383
384        /* private int _selectedAccountIndex;
385         public int SelectedAccountIndex
386         {
387             get { return _selectedAccountIndex; }
388             set
389             {
390                 //var accountCount=Settings.Accounts.Count;
391                 //if (accountCount == 0)
392                 //    return;
393                 //if (0 <= value && value < accountCount)
394                 //    _selectedAccountIndex = value;
395                 //else
396                 //    _selectedAccountIndex = 0;
397                 _selectedAccountIndex = value;
398                 NotifyOfPropertyChange(() => CurrentAccount);
399                 NotifyOfPropertyChange(() => CanRemoveAccount);
400                 NotifyOfPropertyChange(()=>SelectedAccountIndex);
401             }
402         }*/
403
404         private AccountSettings _currentAccount;
405         private IWindowManager _windowManager;
406         private string _shortcutPath;
407
408
409         
410         public AccountSettings CurrentAccount
411         {
412             get { return _currentAccount; }
413             set
414             {
415                 _currentAccount = value;
416                 NotifyOfPropertyChange(()=>CurrentAccount);
417                 NotifyOfPropertyChange(() => CanRemoveAccount);
418                 NotifyOfPropertyChange(() => CanSelectiveSyncFolders);
419                 NotifyOfPropertyChange(() => CanMoveAccountFolder);
420             }
421         }
422
423 /*
424         public AccountSettings CurrentAccount
425         {
426             get {
427                 if (0 <= SelectedAccountIndex && SelectedAccountIndex < Settings.Accounts.Count)                    
428                     return Settings.Accounts[SelectedAccountIndex];
429                 return null;
430             }
431
432         }
433 */
434
435
436         public bool CanMoveAccountFolder
437         {
438             get { return CurrentAccount != null; }
439         }
440
441     public void MoveAccountFolder()
442     {
443
444         using (var dlg = new FolderBrowserDialog())
445         {
446             var currentFolder = CurrentAccount.RootPath;
447             dlg.SelectedPath = currentFolder;
448             //Ask the user to select a folder
449             //Note: We need a parent window here, which we retrieve with GetView            
450             var view = (Window)GetView();            
451             if (DialogResult.OK != dlg.ShowDialog(new Wpf32Window(view)))
452                 return;            
453
454             var newPath= dlg.SelectedPath;                
455             //Find the account's monitor and stop it
456             PithosMonitor monitor;
457             if (Shell.Monitors.TryGetValue(CurrentAccount.AccountName, out monitor))
458             {
459                 monitor.Stop();
460
461
462                 var oldPath = monitor.RootPath;
463                 //The old directory may not exist eg. if we create an account for the first time
464                 if (Directory.Exists(oldPath))
465                 {
466                     //If it does, do the move
467
468                     //Now Create all of the directories
469                     foreach (string dirPath in Directory.EnumerateDirectories(oldPath, "*",
470                                                            SearchOption.AllDirectories))
471                         Directory.CreateDirectory(dirPath.Replace(oldPath, newPath));
472
473                     //Copy all the files
474                     foreach (string newFilePath in Directory.EnumerateFiles(oldPath, "*.*",
475                                                                             SearchOption.AllDirectories))
476                         File.Copy(newFilePath, newFilePath.Replace(oldPath, newPath));
477
478                     Directory.Delete(oldPath, true);
479
480                     //We also need to change the path of the existing file states
481                     if (monitor != null)
482                         monitor.MoveFileStates(oldPath, newPath);
483                 }
484             }
485             //Replace the old rootpath with the new
486             CurrentAccount.RootPath = newPath;
487             //TODO: This will save all settings changes. Too coarse grained, need to fix at a later date
488             Settings.Save();            
489             //And start the monitor on the new RootPath            
490             if (monitor != null)
491             {
492                 monitor.RootPath = newPath;
493                 if (CurrentAccount.IsActive)
494                     monitor.Start();
495             }
496             else
497                 Shell.MonitorAccount(CurrentAccount);
498             //Finally, notify that the Settings, CurrentAccount have changed
499             NotifyOfPropertyChange(() => CurrentAccount);
500             NotifyOfPropertyChange(() => Settings);
501
502         }
503     }
504     }
505 }