0683244ae55479a216ade8ac2a049196d8d00767
[pithos-ms-client] / trunk%2FPithos.Client.WPF%2FFileProperties%2FContainerPropertiesViewModel.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 readonly ObservableCollection<MetaValue> _tags;
287         public ObservableCollection<MetaValue> Tags
288         {
289             get { return _tags; }
290         }
291
292        /* private readonly ObservableCollection<MetaValue> _policies;
293         public ObservableCollection<MetaValue> Policies
294         {
295             get { return _policies; }
296         }*/
297
298         private bool _tagsChanged;
299         public bool TagsChanged
300         {
301             get { return _tagsChanged; }
302             private set
303             {
304                 _tagsChanged = value;
305                 NotifyOfPropertyChange(()=>TagsChanged);
306                 NotifyOfPropertyChange(() => CanApplyChanges);
307             }
308         }
309
310         //public bool PoliciesChanged { get; private set; }
311
312         private bool _isBusy=true;
313         public bool IsBusy
314         {
315             get { return _isBusy; }
316             set
317             {
318                 _isBusy = value;
319                 NotifyOfPropertyChange(()=>IsBusy);
320             }
321         }
322
323         public ContainerPropertiesViewModel(ShellViewModel shell, Task<ContainerInfo> container, string localFolderName)
324         {
325             if (shell==null)
326                 throw new ArgumentNullException("shell");
327             if (container==null)
328                 throw new ArgumentNullException("container");
329             if (String.IsNullOrWhiteSpace(localFolderName))
330                 throw new ArgumentNullException("localFolderName");
331             Contract.EndContractBlock();
332             
333             _tags = new ObservableCollection<MetaValue>();
334             _tags.CollectionChanged += (sender, evt) => { TagsChanged = true; };
335
336             /*_policies = new ObservableCollection<MetaValue>();
337             _policies.CollectionChanged += (sender, evt) => { PoliciesChanged = true; };
338 */
339
340             Shell = shell;
341             ContainerName = localFolderName;
342             container.ContinueWith(t =>{                
343                 if (t.IsFaulted)
344                 {
345                     IsBusy = false;
346                     Execute.OnUIThread(() => ShowError(t.Exception));
347                     this.TryClose();
348
349                 }
350                 else
351                     Execute.OnUIThread(()=>Container = t.Result);                                           
352             });
353         }
354
355         private void ShowError(AggregateException exception)
356         {
357             MessageView view=null;
358             if (exception.InnerException is RetryException)
359                 view=new MessageView(exception.InnerException as RetryException);
360             else if (exception.InnerException is WebException)
361                 view = new MessageView(exception.InnerException as WebException);
362             else
363                 view = new MessageView(exception.InnerException);
364             view.ShowDialog();
365         }
366
367         public void Reload()
368         {
369             Container = Shell.RefreshContainerInfo(Container);
370         }
371
372         public override void CanClose(Action<bool> callback)
373         {
374             base.CanClose(callback);
375         }
376
377         public void SaveChanges()
378         {
379             DoSave();
380             TryClose();
381         }
382
383         public void RejectChanges()
384         {
385             TryClose();
386         }
387
388         public void ApplyChanges()
389         {
390             DoSave();
391         }
392
393         public bool CanApplyChanges
394         {
395             get { return TagsChanged; }
396         }
397
398         private void DoSave()
399         {
400             
401             if (TagsChanged)
402             {
403                 Container.Tags = this.Tags.ToDictionary(tag => tag.Name, tag => tag.Value);
404                 var monitor = Shell.Monitors[Container.Account];
405                 monitor.CloudClient.UpdateMetadata(Container);
406             }
407
408             //Container.Policies["Quota"] = Quota.ToString();
409             //Container.Policies["Versioning"] = Enum.GetName(typeof (Versioning), SelectedVersion);
410
411 /*
412             if (PoliciesChanged)
413             {
414                 Container.Policies = this.Policies.ToDictionary(policy=> policy.Name, tag => tag.Value);
415             }
416 */
417             
418
419         }
420
421     }
422
423     
424 }