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