Merge branch 'master' of \\\pk2010\Pithos\
[pithos-ms-client] / trunk / Pithos.Client.WPF / FileProperties / FilePropertiesViewModel.cs
1 // -----------------------------------------------------------------------
2 // <copyright file="FilePropertiesViewModel.cs" company="GRNet">
3 // Copyright 2011-2012 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 // </copyright>
36 // -----------------------------------------------------------------------
37
38 using System.Collections;
39 using System.Collections.Concurrent;
40 using System.Collections.ObjectModel;
41 using System.Collections.Specialized;
42 using System.ComponentModel.Composition;
43 using System.Diagnostics;
44 using System.Diagnostics.Contracts;
45 using System.Drawing;
46 using System.IO;
47 using System.Net;
48 using System.Threading.Tasks;
49 using System.Windows;
50 using System.Windows.Interop;
51 using System.Windows.Media.Imaging;
52 using Caliburn.Micro;
53 using Pithos.Client.WPF.FileProperties;
54 using Pithos.Client.WPF.Properties;
55 using Pithos.Core;
56 using Pithos.Interfaces;
57 using Pithos.Network;
58
59 namespace Pithos.Client.WPF
60 {
61     using System;
62     using System.Collections.Generic;
63     using System.Linq;
64     using System.Text;
65
66     /// <summary>
67     /// TODO: Update summary.
68     /// </summary>
69     [Export(typeof(FilePropertiesViewModel))]
70     public class FilePropertiesViewModel : Screen
71     {
72         private string _title;
73         public string Title
74         {
75             get { return _title; }
76             set
77             {
78                 _title = value;
79                 NotifyOfPropertyChange(()=>Title);
80             }
81         }
82
83
84         private bool _isPublic;
85         public bool IsPublic
86         {
87             get { return _isPublic; }
88             set
89             {
90                 _isPublic = value;
91                 NotifyOfPropertyChange(()=>IsPublic);
92             }
93         }
94
95         private string _contentDisposition;
96         public string ContentDisposition
97         {
98             get { return _contentDisposition; }
99             set
100             {
101                 _contentDisposition = value;
102                 NotifyOfPropertyChange(() => ContentDisposition);
103             }
104         }
105
106         private string _contentEncoding;
107         public string ContentEncoding
108         {
109             get { return _contentEncoding; }
110             set
111             {
112                 _contentEncoding = value;
113                 NotifyOfPropertyChange(() => ContentEncoding);
114             }
115         }
116
117
118         private string _manifest;
119         public string Manifest
120         {
121             get { return _manifest; }
122             set
123             {
124                 _manifest = value;
125                 NotifyOfPropertyChange(() => Manifest);
126             }
127         }
128
129         private string _kind;
130         public string Kind
131         {
132             get { return _kind; }
133             set
134             {
135                 _kind = value;
136                 NotifyOfPropertyChange(() => Kind);
137             }
138         }
139
140         private string _size;
141         public string Size
142         {
143             get { return _size; }
144             set
145             {
146                 _size = value;
147                 NotifyOfPropertyChange(() => Size);
148             }
149         }
150
151         private string _shortSize;
152         public string ShortSize
153         {
154             get { return _shortSize; }
155             set
156             {
157                 _shortSize = value;
158                 NotifyOfPropertyChange(() => ShortSize);
159             }
160         }
161
162         private string _where;
163         public string Where
164         {
165             get { return _where; }
166             set
167             {
168                 _where = value;
169                 NotifyOfPropertyChange(() => Where);
170             }
171         }
172
173         private DateTime _modified;
174         public DateTime Modified
175         {
176             get { return _modified; }
177             set
178             {
179                 _modified = value;
180                 NotifyOfPropertyChange(() => Modified);
181             }
182         }
183
184         private string _modifiedBy;
185         public string ModifiedBy
186         {
187             get { return _modifiedBy; }
188             set
189             {
190                 _modifiedBy = value;
191                 NotifyOfPropertyChange(() => ModifiedBy);
192             }
193         }
194
195         private long _version;
196         public long Version
197         {
198             get { return _version; }
199             set
200             {
201                 _version = value;
202                 NotifyOfPropertyChange(() => Version);
203             }
204         }
205
206         private string _localFileName;
207         protected string LocalFileName
208         {
209             get { return _localFileName; }
210             set
211             {
212                 _localFileName = value;
213                 NotifyOfPropertyChange(() => LocalFileName);
214             }
215         }
216
217         private BitmapSource _fileIcon;
218         public BitmapSource FileIcon
219         {
220             get { return _fileIcon; }
221             set
222             {
223                 _fileIcon = value;
224                 NotifyOfPropertyChange(() => FileIcon);
225             }
226         }
227
228         private string _publicUrl;
229         public string PublicUrl
230         {
231             get { return _publicUrl; }
232             set
233             {
234                 _publicUrl = value;
235                 NotifyOfPropertyChange(() => PublicUrl);
236             }
237         }
238
239         private string _fileName;
240         public string FileName
241         {
242             get { return _fileName; }
243             set
244             {
245                 _fileName = value;
246                 NotifyOfPropertyChange(() => FileName);
247             }
248         }
249
250         private string _container;
251         public string Container
252         {
253             get { return _container; }
254             set
255             {
256                 _container = value;
257                 NotifyOfPropertyChange(() => Container);
258             }
259         }
260
261         private string _synchStatus;
262         public string SynchStatus
263         {
264             get { return _synchStatus; }
265             set
266             {
267                 _synchStatus = value;
268                 NotifyOfPropertyChange(()=>SynchStatus);
269             }
270         }
271
272         public bool TagsChanged { get; private set; }
273         public bool PermissionsChanged { get; private set; }
274
275         private bool _isBusy = true;
276         public bool IsBusy
277         {
278             get { return _isBusy; }
279             set
280             {
281                 _isBusy = value;
282                 NotifyOfPropertyChange(() => IsBusy);
283             }
284         }
285
286
287         public FilePropertiesViewModel(ShellViewModel shell,Task<ObjectInfo> pithosFile,string localFileName)
288         {
289             if (shell==null)
290                 throw new ArgumentNullException("shell");
291             if (pithosFile==null)
292                 throw new ArgumentNullException("pithosFile");
293             if (String.IsNullOrWhiteSpace(localFileName))
294                 throw new ArgumentNullException("localFileName");
295             Contract.EndContractBlock();
296
297
298             _tags = new ObservableCollection<MetaValue>();
299             _tags.CollectionChanged += (sender, evt) => { TagsChanged = true; };
300             _permissions = new ObservableCollection<Permission>();
301             _permissions.CollectionChanged += (sender, evt) => { PermissionsChanged = true; };
302             
303             Shell = shell;
304             LocalFileName = localFileName;
305             pithosFile.ContinueWith(t =>
306             {
307                 if (t.IsFaulted)
308                 {
309                     IsBusy = false;
310                     Execute.OnUIThread(()=>ShowError(t.Exception));
311                     this.TryClose();
312
313                 }
314                 else
315                     Execute.OnUIThread(() => PithosFile = t.Result);
316             });       
317                  
318         }
319
320         private void ShowError(AggregateException exception)
321         {
322             MessageView view = null;
323             if (exception.InnerException is RetryException)
324                 view = new MessageView(exception.InnerException as RetryException);
325             else if (exception.InnerException is WebException)
326                 view = new MessageView(exception.InnerException as WebException);
327             else
328                 view = new MessageView(exception.InnerException);
329             view.ShowDialog();
330         }
331
332
333         protected ShellViewModel Shell { get; set; }
334
335         private ObjectInfo _pithosFile;
336         public ObjectInfo PithosFile
337         {
338             get { return _pithosFile; }
339             set
340             {
341                 _pithosFile = value;
342                 
343                 Permissions.Clear();
344                 Tags.Clear();
345
346                 var perms=from permission in value.Permissions
347                             select new Permission(permission.Key, permission.Value);
348                 perms.Apply(perm=>Permissions.Add(perm));
349                 
350                 var tags=from tag in value.Tags
351                              select new MetaValue(tag.Key, tag.Value);
352                 tags.Apply(tag=>Tags.Add(tag));
353
354                 Title = String.Format("{0} Properties", value.Name);
355                 Kind=value.Content_Type;
356                 ShortSize = value.Bytes.ToByteSize();
357                 Size = String.Format("{0} ({1:N0} bytes)", ShortSize, value.Bytes);
358                 Where = Uri.UnescapeDataString(value.Name);
359                 FileName = Uri.UnescapeDataString(value.Name.Split('/').Last());
360                 Container = value.Container;
361                 Modified = value.Last_Modified;
362                 ModifiedBy = value.ModifiedBy;
363                 Version = value.Version??0;
364
365                 ContentDisposition = value.ContendDisposition;
366                 ContentEncoding = value.ContentEncoding;
367                 Manifest = value.Manifest;
368                 IsPublic = value.IsPublic;
369                 if (IsPublic)
370                     PublicUrl = String.Format("{0}/v1{1}", Shell.Accounts.First(account=>account.UserName==PithosFile.Account).SiteUri,value.PublicUrl);
371
372                 if (Directory.Exists(LocalFileName))
373                 {
374                     FileIcon= new BitmapImage(new Uri("../Images/Folder.ico",UriKind.Relative));
375                 }
376                 else if (File.Exists(LocalFileName))
377                 {
378                     using (var icon = Icon.ExtractAssociatedIcon(LocalFileName))
379                     {
380                         FileIcon = Imaging.CreateBitmapSourceFromHIcon(icon.Handle, Int32Rect.Empty,
381                                                                        BitmapSizeOptions.FromEmptyOptions());
382                     }
383                 }
384
385                 var status=Shell.GetFileStatus(LocalFileName);
386                 SynchStatus = Enum.GetName(typeof (FileStatus), status);
387
388
389                 NotifyOfPropertyChange(()=>PithosFile);
390                 IsBusy = false;
391             }
392         }
393
394
395         private readonly ObservableCollection<MetaValue> _tags ;
396         public ObservableCollection<MetaValue> Tags
397         {
398             get { return _tags;}
399         }
400
401         private readonly ObservableCollection<Permission> _permissions ;
402         
403
404         public ObservableCollection<Permission> Permissions
405         {
406             get { return _permissions; }
407         }
408
409         public void Reload()
410         {
411             PithosFile=Shell.RefreshObjectInfo(PithosFile);
412         }
413
414         public override void CanClose(Action<bool> callback)
415         {
416             base.CanClose(callback);
417         }
418
419         public void SaveChanges()
420         {
421             DoSave();
422             TryClose();
423         }
424
425         public void RejectChanges()
426         {
427             TryClose();
428         }
429
430         public void ApplyChanges()
431         {
432             DoSave();
433         }
434
435         private void DoSave()
436         {
437             if (TagsChanged)
438             {
439                 PithosFile.Tags = this.Tags.ToDictionary(tag => tag.Name, tag => tag.Value);
440             }
441             
442             if (PermissionsChanged)
443             {
444                 PithosFile.Permissions = this.Permissions.ToDictionary(perm => perm.UserName, perm => perm.Value);
445             }
446
447             PithosFile.ContendDisposition = ContentDisposition;
448             PithosFile.ContentEncoding = ContentEncoding;
449             PithosFile.Manifest = Manifest;
450             PithosFile.IsPublic = IsPublic;
451
452             var monitor = Shell.Monitors[PithosFile.Account];
453             monitor.CloudClient.UpdateMetadata(PithosFile);
454
455
456             TagsChanged = false;
457             PermissionsChanged = false;
458         }
459
460
461     }
462 }