The Tags tab of ContainerPropertiesView.xaml now works in a similar way to FileProper...
[pithos-ms-client] / trunk / Pithos.Client.WPF / FileProperties / ContainerPropertiesViewModel.cs
1 #region
2 /* -----------------------------------------------------------------------
3  * <copyright file="ContainerPropertiesViewModel.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 using System;
43 using System.Collections.Concurrent;
44 using System.Collections.Generic;
45 using System.Collections.ObjectModel;
46 using System.ComponentModel.Composition;
47 using System.Diagnostics.Contracts;
48 using System.Linq;
49 using System.Net;
50 using System.Text;
51 using System.Threading.Tasks;
52 using System.Windows;
53 using Caliburn.Micro;
54 using Pithos.Network;
55
56 namespace Pithos.Client.WPF.FileProperties
57 {
58     [Export(typeof(ContainerPropertiesViewModel))]
59     public class ContainerPropertiesViewModel:Screen
60     {
61         private string _containerName;
62
63         /// <summary>
64         /// Name of the displayed container
65         /// </summary>
66         public string ContainerName
67         {
68             get { return _containerName; }
69             set
70             {
71                 _containerName = value;
72                 NotifyOfPropertyChange(()=>ContainerName);
73             }
74         }
75
76         private string _title;
77         /// <summary>
78         /// Window title
79         /// </summary>
80         public string Title
81         {
82             get { return _title; }
83             set
84             {
85                 _title = value;
86                 NotifyOfPropertyChange(() => Title);
87             }
88         }
89
90         private long _count;
91
92         /// <summary>
93         /// Count of files in the container
94         /// </summary>
95         public long Count
96         {
97             get { return _count; }
98             set
99             {
100                 _count = value;
101                 NotifyOfPropertyChange(() => Count);
102             }
103         }
104
105         private DateTime _modified;
106
107         /// <summary>
108         /// Date of last modification
109         /// </summary>
110         public DateTime Modified
111         {
112             get { return _modified; }
113             set
114             {
115                 _modified = value;
116                 NotifyOfPropertyChange(() => Modified);
117             }
118         }
119
120         private string _size;
121
122         /// <summary>
123         /// Total size of the container in bytes
124         /// </summary>
125         public string Size
126         {
127             get { return _size; }
128             set
129             {
130                 _size = value;
131                 NotifyOfPropertyChange(() => Size);
132             }
133         }
134
135         private string _shortSize;
136
137         /// <summary>
138         /// Total size of the container formatted in KB,MB etc
139         /// </summary>
140         public string ShortSize
141         {
142             get { return _shortSize; }
143             set
144             {
145                 _shortSize = value;
146                 NotifyOfPropertyChange(() => ShortSize);
147             }
148         }
149
150         private int _blockSize;
151
152         /// <summary>
153         /// Block size used by the container
154         /// </summary>
155         public int BlockSize
156         {
157             get { return _blockSize; }
158             set
159             {
160                 _blockSize = value;
161                 NotifyOfPropertyChange(() => BlockSize);
162             }
163         }
164
165         private string _blockHash;
166
167         /// <summary>
168         /// Hash algorithm used to calculate block hashes
169         /// </summary>
170         public string BlockHash
171         {
172             get { return _blockHash; }
173             set
174             {
175                 _blockHash = value;
176                 NotifyOfPropertyChange(() => BlockHash);
177             }
178         }
179
180         private ShellViewModel _shell;
181
182         /// <summary>
183         /// Reference to the parent Shell
184         /// </summary>
185         protected ShellViewModel Shell
186         {
187             get { return _shell; }
188             set
189             {
190                 _shell = value;
191                 NotifyOfPropertyChange(() => Shell);
192             }
193         }
194
195         private ContainerInfo _container;
196         /// <summary>
197         /// The displayed ContainerInfo
198         /// </summary>
199         protected ContainerInfo Container
200         {
201             get { return _container; }
202             set
203             {
204                 _container = value;
205
206                 
207
208                 LoadFromDictionary(Tags, value.Tags);
209                 TagsChanged = false;
210                 //LoadFromDictionary(Policies, value.Policies);
211
212                 if (value.Policies.ContainsKey("Versioning"))
213                 {
214                     Versioning version;
215                     if (Enum.TryParse(value.Policies["Versioning"], out version))
216                     {
217                         SelectedVersion = version;
218                     }
219                 }
220
221                 if (value.Policies.ContainsKey("Quota"))
222                 {
223                     int quota;
224                     if (int.TryParse(value.Policies["Quota"], out quota))
225                     {
226                         Quota=quota;
227                     }
228                 }
229
230                 Title = String.Format("{0} Properties", _container.Name);
231                 Count = value.Count;
232                 ShortSize = value.Bytes.ToByteSize();
233                 Size = String.Format("{0} ({1:N0} bytes)", ShortSize, value.Bytes);
234                 Modified = value.Last_Modified;
235                 BlockSize = value.BlockSize;
236                 BlockHash = value.BlockHash;                
237                 ContainerName = Uri.UnescapeDataString(value.Name.Split('/').Last());                                                
238
239                 NotifyOfPropertyChange(() => Container);
240                 IsBusy = false;
241             }
242         }
243
244         private int _quota;
245         public int Quota
246         {
247             get { return _quota; }
248             set
249             {
250                 if (value < 0)
251                     throw new ArgumentOutOfRangeException("Quota");
252
253                 _quota = value;                
254                 NotifyOfPropertyChange(() => Quota);
255             }
256         }
257
258
259
260         private Versioning[] _versions={Versioning.manual,Versioning.auto,Versioning.none};
261         public Versioning[] Versions
262         {
263             get { return _versions; }
264         }
265
266
267         private Versioning _selectedVersion;
268         public Versioning SelectedVersion
269         {
270             get { return _selectedVersion; }
271             set { 
272                 _selectedVersion = value;
273                 NotifyOfPropertyChange(()=>SelectedVersion);
274             }
275         }
276
277         private void LoadFromDictionary(ICollection<MetaValue> collection,Dictionary<string,string> source  )
278         {
279             collection.Clear();
280             var items = from item in source
281                         select new MetaValue(item.Key, item.Value);
282             
283             items.Apply(collection.Add);
284         }
285
286         private MetaValue _currentTag;
287         public MetaValue CurrentTag
288         {
289             get { return _currentTag; }
290             set
291             {
292                 _currentTag = (value == null) ? new MetaValue() : value.Clone();
293                 _currentTag.PropertyChanged += (o, e) => NotifyOfPropertyChange(() => CanAddTag);
294
295                 NotifyOfPropertyChange(() => CurrentTag);
296                 NotifyOfPropertyChange(() => CanAddTag);
297             }
298         }
299
300         private readonly ObservableCollection<MetaValue> _tags;
301         public ObservableCollection<MetaValue> Tags
302         {
303             get { return _tags; }
304         }
305
306         public bool CanAddTag
307         {
308             get { return !String.IsNullOrWhiteSpace(CurrentTag.Name); }
309         }
310
311         public void AddTag()
312         {
313             var existingTag = Tags.FirstOrDefault(tag => tag.Name == CurrentTag.Name);
314             if (existingTag == null)
315                 Tags.Add(CurrentTag.Clone());
316             else
317             {
318                 existingTag.Value = CurrentTag.Value;
319             }
320         }
321
322        /* private readonly ObservableCollection<MetaValue> _policies;
323         public ObservableCollection<MetaValue> Policies
324         {
325             get { return _policies; }
326         }*/
327
328         private bool _tagsChanged;
329         public bool TagsChanged
330         {
331             get { return _tagsChanged; }
332             private set
333             {
334                 _tagsChanged = value;
335                 NotifyOfPropertyChange(()=>TagsChanged);
336                 NotifyOfPropertyChange(() => CanApplyChanges);
337             }
338         }
339
340         //public bool PoliciesChanged { get; private set; }
341
342         private bool _isBusy=true;
343         public bool IsBusy
344         {
345             get { return _isBusy; }
346             set
347             {
348                 _isBusy = value;
349                 NotifyOfPropertyChange(()=>IsBusy);
350             }
351         }
352
353         public ContainerPropertiesViewModel(ShellViewModel shell, Task<ContainerInfo> container, string localFolderName)
354         {
355             if (shell==null)
356                 throw new ArgumentNullException("shell");
357             if (container==null)
358                 throw new ArgumentNullException("container");
359             if (String.IsNullOrWhiteSpace(localFolderName))
360                 throw new ArgumentNullException("localFolderName");
361             Contract.EndContractBlock();
362             
363             _tags = new ObservableCollection<MetaValue>();
364             _tags.CollectionChanged += (sender, evt) => { TagsChanged = true; };
365
366             /*_policies = new ObservableCollection<MetaValue>();
367             _policies.CollectionChanged += (sender, evt) => { PoliciesChanged = true; };
368 */
369
370             Shell = shell;
371             ContainerName = localFolderName;
372             container.ContinueWith(t =>{                
373                 if (t.IsFaulted)
374                 {
375                     IsBusy = false;
376                     Execute.OnUIThread(() => ShowError(t.Exception));
377                     this.TryClose();
378
379                 }
380                 else
381                     Execute.OnUIThread(()=>Container = t.Result);                                           
382             });
383         }
384
385         private void ShowError(AggregateException exception)
386         {
387             MessageView view=null;
388             if (exception.InnerException is RetryException)
389                 view=new MessageView(exception.InnerException as RetryException);
390             else if (exception.InnerException is WebException)
391                 view = new MessageView(exception.InnerException as WebException);
392             else
393                 view = new MessageView(exception.InnerException);
394             view.ShowDialog();
395         }
396
397         public void Reload()
398         {
399             Container = Shell.RefreshContainerInfo(Container);
400         }
401
402         public override void CanClose(Action<bool> callback)
403         {
404             base.CanClose(callback);
405         }
406
407         public void SaveChanges()
408         {
409             DoSave();
410             TryClose();
411         }
412
413         public void RejectChanges()
414         {
415             TryClose();
416         }
417
418         public void ApplyChanges()
419         {
420             DoSave();
421         }
422
423         public bool CanApplyChanges
424         {
425             get { return TagsChanged; }
426         }
427
428         private void DoSave()
429         {
430             
431             if (TagsChanged)
432             {
433                 Container.Tags = this.Tags.ToDictionary(tag => tag.Name, tag => tag.Value);
434                 var monitor = Shell.Monitors[Container.AccountKey];
435                 monitor.CloudClient.UpdateMetadata(Container);
436             }
437
438             //Container.Policies["Quota"] = Quota.ToString();
439             //Container.Policies["Versioning"] = Enum.GetName(typeof (Versioning), SelectedVersion);
440
441 /*
442             if (PoliciesChanged)
443             {
444                 Container.Policies = this.Policies.ToDictionary(policy=> policy.Name, tag => tag.Value);
445             }
446 */
447             
448
449         }
450
451     }
452
453     
454 }