Finished account wizard that allows adding an account either by logging to the Pithos...
[pithos-ms-client] / trunk / Pithos.Client.WPF / Preferences / PreferencesViewModel.cs
1 // -----------------------------------------------------------------------
2 // <copyright file="PreferencesViewModel.cs" company="Microsoft">
3 // TODO: Update copyright text.
4 // </copyright>
5 // -----------------------------------------------------------------------
6
7 using System.Collections.Concurrent;
8 using System.ComponentModel.Composition;
9 using System.IO;
10 using System.Reflection;
11 using System.Windows;
12 using System.Windows.Forms;
13 using Caliburn.Micro;
14 using IWshRuntimeLibrary;
15 using Pithos.Client.WPF.Configuration;
16 using Pithos.Client.WPF.Preferences;
17 using Pithos.Client.WPF.SelectiveSynch;
18 using Pithos.Core;
19 using Pithos.Interfaces;
20 using File = System.IO.File;
21 using Screen = Caliburn.Micro.Screen;
22
23 namespace Pithos.Client.WPF
24 {
25     using System;
26     using System.Linq;
27     using System.Threading.Tasks;
28
29     /// <summary>
30     /// TODO: Update summary.
31     /// </summary>
32     [Export]
33     public class PreferencesViewModel : Screen
34     {
35         private IEventAggregator _events;
36
37
38         private PithosSettings _settings;
39         public PithosSettings Settings
40         {
41             get { return _settings; }
42             set
43             {
44                 _settings = value;
45                 NotifyOfPropertyChange(()=>Settings);
46             }
47         }
48
49         private ObservableConcurrentCollection<AccountSettings> _accounts;
50         public ObservableConcurrentCollection<AccountSettings> Accounts
51         {
52             get { return _accounts; }
53             set 
54             { 
55                 _accounts = value;
56                 NotifyOfPropertyChange(()=>Accounts);
57             }
58         }
59         
60         public bool StartOnSystemStartup { get; set; }
61
62         private static void CreateShortcut(string shortcutPath)
63         {
64             var wshShell = new WshShellClass();
65             var shortcut = (IWshRuntimeLibrary.IWshShortcut) wshShell.CreateShortcut(
66                 shortcutPath);
67
68             var exePath = Assembly.GetExecutingAssembly().Location;
69             shortcut.TargetPath = exePath;
70             shortcut.WorkingDirectory = Path.GetDirectoryName(exePath);
71             shortcut.Description = "Pithos";            
72             shortcut.Save();
73         }
74
75         public ShellViewModel Shell { get;  set; }
76         //ShellExtensionController _extensionController=new ShellExtensionController();
77
78         public PreferencesViewModel(IWindowManager windowManager, IEventAggregator events, ShellViewModel shell, PithosSettings settings)
79         {
80             _windowManager = windowManager;
81             _events = events;
82
83             DisplayName = "Pithos Preferences";
84             Shell = shell;
85
86             Settings=settings;
87             Accounts = new ObservableConcurrentCollection<AccountSettings>();
88             Accounts.AddFromEnumerable(settings.Accounts);
89             
90             var startupPath = Environment.GetFolderPath(Environment.SpecialFolder.Startup);
91             _shortcutPath = Path.Combine(startupPath, "Pithos.lnk");
92
93
94             StartOnSystemStartup = File.Exists(_shortcutPath);
95
96         }
97
98
99         #region Preferences Properties
100
101         private bool _noProxy;
102         public bool NoProxy
103         {
104             get { return _noProxy; }
105             set
106             {
107                 _noProxy = value;
108                 NotifyOfPropertyChange(()=>NoProxy);
109             }
110         }
111
112
113         private bool _defaultProxy;
114
115         public bool DefaultProxy
116         {
117             get { return _defaultProxy; }
118             set
119             {
120                 _defaultProxy = value;
121                 NotifyOfPropertyChange(() => DefaultProxy);
122             }
123         }
124
125
126         private bool _manualProxy;
127
128         public bool ManualProxy
129         {
130             get { return _manualProxy; }
131             set
132             {
133                 _manualProxy = value;
134                 NotifyOfPropertyChange(() => ManualProxy);
135             }
136         }
137         #endregion
138
139        
140         #region Commands
141         
142         public bool CanSelectiveSyncFolders
143         {
144             get { return CurrentAccount != null; }
145         }
146
147         public void SelectiveSyncFolders()
148         {
149             var monitor = Shell.Monitors[CurrentAccount.AccountName];
150             var folders=monitor.GetRootFolders();
151
152             var model = new SelectiveSynchViewModel(folders,_events,CurrentAccount);
153             if (_windowManager.ShowDialog(model) == true)
154             {
155                 
156             }
157         }
158     
159         public void SaveChanges()
160         {
161             DoSave();
162             TryClose(true);
163         }
164
165         public void RejectChanges()
166         {
167             Settings.Reload();
168             TryClose(false);
169         }
170
171         public void ApplyChanges()
172         {
173             DoSave();
174         }
175
176         private void DoSave()
177         {
178             Settings.Save();
179             SetStartupMode();
180
181
182             foreach (var account in Settings.Accounts)
183             {                                
184                 Shell.MonitorAccount(account);
185             }
186
187             NotifyOfPropertyChange(()=>Settings);
188         }
189
190         private void SetStartupMode()
191         {
192             if (StartOnSystemStartup && !File.Exists(_shortcutPath))
193             {
194                 CreateShortcut(_shortcutPath);
195             }
196             else if (!StartOnSystemStartup && File.Exists(_shortcutPath))
197             {
198                 if (File.Exists(_shortcutPath))
199                     File.Delete(_shortcutPath);
200             }
201         }
202
203      /*   public void ChangePithosFolder()
204         {
205             var browser = new FolderBrowserDialog();
206             browser.SelectedPath = Settings.PithosPath;
207             var result = browser.ShowDialog((IWin32Window)GetView());
208             if (result == DialogResult.OK)
209             {
210                 var newPath = browser.SelectedPath;
211                 var accountName = CurrentAccount.AccountName;
212                 var monitor = Shell.Monitors[accountName];
213                 monitor.Stop();
214                 
215                 Shell.Monitors.Remove(accountName);
216
217                 Directory.Move(Settings.PithosPath, newPath);
218                 Settings.PithosPath = newPath;
219                 Settings.Save();
220
221                 Shell.MonitorAccount(CurrentAccount);
222
223                 NotifyOfPropertyChange(() => Settings);                
224             }
225         }
226 */
227        public void AddAccount()
228        {
229            var wizard = new AddAccountViewModel();
230            if (_windowManager.ShowDialog(wizard) == true)
231            {
232                var newAccount = new AccountSettings
233                                     {
234                                         AccountName = wizard.AccountName,
235                                         ApiKey=wizard.Token,
236                                         RootPath=wizard.AccountPath,
237                                         IsActive=wizard.IsAccountActive,
238                                         UsePithos=true
239                                     };
240                Settings.Accounts.Add(newAccount);
241                (Accounts as IProducerConsumerCollection<AccountSettings>).TryAdd(newAccount);
242                CurrentAccount = newAccount;
243                NotifyOfPropertyChange(() => Accounts);
244                NotifyOfPropertyChange(() => Settings);   
245            }
246
247
248             
249        }
250
251         public async void AddPithosAccount()
252        {
253             var credentials=await PithosAccount.RetrieveCredentialsAsync(Settings.PithosLoginUrl);
254             var account = Settings.Accounts.FirstOrDefault(act => act.AccountName == credentials.UserName);
255             if (account == null)
256             {
257                 account=new AccountSettings{
258                     AccountName=credentials.UserName,
259                     ApiKey=credentials.Password,
260                     UsePithos=true
261                 };
262                 Settings.Accounts.Add(account);
263                 (Accounts as IProducerConsumerCollection<AccountSettings>).TryAdd(account);
264             }
265             else
266             {
267                 account.ApiKey=credentials.Password;
268             }
269             //SelectedAccountIndex= Settings.Accounts.IndexOf(account);
270             CurrentAccount = account;
271             NotifyOfPropertyChange(() => Accounts);
272             NotifyOfPropertyChange(()=>Settings);                       
273        }
274
275         public void RemoveAccount()
276         {
277             var accountName = CurrentAccount.AccountName;
278             Settings.Accounts.Remove(CurrentAccount);
279
280             Accounts.TryRemove(CurrentAccount);
281             
282             
283             CurrentAccount = null;
284             //Accounts = Settings.Accounts;
285             //Settings.Save();            
286             Shell.RemoveMonitor(accountName);
287             
288             //NotifyOfPropertyChange("Settings.Accounts");
289         }
290
291         public bool CanRemoveAccount
292         {
293             get { return (CurrentAccount != null); }
294         }
295
296
297
298         public bool ExtensionsActivated
299         {
300             get { return Settings.ExtensionsActivated; }
301             set
302             {
303                 if (Settings.ExtensionsActivated == value)
304                     return;
305
306                 Settings.ExtensionsActivated = value;
307
308 /*
309                 if (value)
310                     _extensionController.RegisterExtensions();
311                 else
312                 {
313                     _extensionController.UnregisterExtensions();
314                 }
315 */
316                 NotifyOfPropertyChange(() => ExtensionsActivated);
317             }
318         }
319
320        
321         #endregion
322
323        /* private int _selectedAccountIndex;
324         public int SelectedAccountIndex
325         {
326             get { return _selectedAccountIndex; }
327             set
328             {
329                 //var accountCount=Settings.Accounts.Count;
330                 //if (accountCount == 0)
331                 //    return;
332                 //if (0 <= value && value < accountCount)
333                 //    _selectedAccountIndex = value;
334                 //else
335                 //    _selectedAccountIndex = 0;
336                 _selectedAccountIndex = value;
337                 NotifyOfPropertyChange(() => CurrentAccount);
338                 NotifyOfPropertyChange(() => CanRemoveAccount);
339                 NotifyOfPropertyChange(()=>SelectedAccountIndex);
340             }
341         }*/
342
343         private AccountSettings _currentAccount;
344         private IWindowManager _windowManager;
345         private string _shortcutPath;
346
347
348         
349         public AccountSettings CurrentAccount
350         {
351             get { return _currentAccount; }
352             set
353             {
354                 _currentAccount = value;
355                 NotifyOfPropertyChange(()=>CurrentAccount);
356                 NotifyOfPropertyChange(() => CanRemoveAccount);
357                 NotifyOfPropertyChange(() => CanSelectiveSyncFolders);
358                 NotifyOfPropertyChange(() => CanMoveAccountFolder);
359             }
360         }
361
362 /*
363         public AccountSettings CurrentAccount
364         {
365             get {
366                 if (0 <= SelectedAccountIndex && SelectedAccountIndex < Settings.Accounts.Count)                    
367                     return Settings.Accounts[SelectedAccountIndex];
368                 return null;
369             }
370
371         }
372 */
373
374
375         public bool CanMoveAccountFolder
376         {
377             get { return CurrentAccount != null; }
378         }
379
380     public void MoveAccountFolder()
381     {
382
383         using (var dlg = new FolderBrowserDialog())
384         {
385             var currentFolder = CurrentAccount.RootPath;
386             dlg.SelectedPath = currentFolder;
387             //Ask the user to select a folder
388             //Note: We need a parent window here, which we retrieve with GetView            
389             var view = (Window)GetView();            
390             if (DialogResult.OK != dlg.ShowDialog(new Wpf32Window(view)))
391                 return;            
392
393             var newPath= dlg.SelectedPath;                
394             //Find the account's monitor and stop it
395             PithosMonitor monitor;
396             if (Shell.Monitors.TryGetValue(CurrentAccount.AccountName, out monitor))
397             {
398                 monitor.Stop();
399
400
401                 var oldPath = monitor.RootPath;
402                 //The old directory may not exist eg. if we create an account for the first time
403                 if (Directory.Exists(oldPath))
404                 {
405                     //If it does, do the move
406
407                     //Now Create all of the directories
408                     foreach (string dirPath in Directory.EnumerateDirectories(oldPath, "*",
409                                                            SearchOption.AllDirectories))
410                         Directory.CreateDirectory(dirPath.Replace(oldPath, newPath));
411
412                     //Copy all the files
413                     foreach (string newFilePath in Directory.EnumerateFiles(oldPath, "*.*",
414                                                                             SearchOption.AllDirectories))
415                         File.Copy(newFilePath, newFilePath.Replace(oldPath, newPath));
416
417                     Directory.Delete(oldPath, true);
418
419                     //We also need to change the path of the existing file states
420                     if (monitor != null)
421                         monitor.MoveFileStates(oldPath, newPath);
422                 }
423             }
424             //Replace the old rootpath with the new
425             CurrentAccount.RootPath = newPath;
426             //TODO: This will save all settings changes. Too coarse grained, need to fix at a later date
427             Settings.Save();            
428             //And start the monitor on the new RootPath            
429             if (monitor != null)
430             {
431                 monitor.RootPath = newPath;
432                 if (CurrentAccount.IsActive)
433                     monitor.Start();
434             }
435             else
436                 Shell.MonitorAccount(CurrentAccount);
437             //Finally, notify that the Settings, CurrentAccount have changed
438             NotifyOfPropertyChange(() => CurrentAccount);
439             NotifyOfPropertyChange(() => Settings);
440
441         }
442     }
443     }
444 }