Fix to Selective Synch check behavior
[pithos-ms-client] / trunk / Pithos.Client.WPF / SelectiveSynch / SelectiveSynchViewModel.cs
1 #region
2 /* -----------------------------------------------------------------------
3  * <copyright file="SelectiveSynchViewModel.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.Generic;
44 using System.Collections.ObjectModel;
45 using System.Collections.Specialized;
46 using System.IO;
47 using System.Linq;
48 using System.Text;
49 using System.Threading.Tasks;
50 using Caliburn.Micro;
51 using Pithos.Client.WPF.Properties;
52 using Pithos.Core;
53 using Pithos.Core.Agents;
54 using Pithos.Interfaces;
55 using Pithos.Network;
56
57 namespace Pithos.Client.WPF.SelectiveSynch
58 {
59     class SelectiveSynchViewModel:Screen
60     {
61         private const string DirectoryType = "application/directory";
62         private IEventAggregator _events ;
63
64         private string _title;
65         public string Title
66         {
67             get { return _title; }
68             set
69             {
70                 _title = value;
71                 NotifyOfPropertyChange(() => Title);
72             }
73         }
74
75         public AccountSettings Account { get; set; }
76
77         private readonly ObservableCollection<DirectoryRecord> _rootNodes=new ObservableCollection<DirectoryRecord>();
78         public ObservableCollection<DirectoryRecord> RootNodes
79         {
80             get { return _rootNodes; }
81         }
82
83         private ObservableCollection<ObjectInfo> _checks;
84         private PithosMonitor _monitor;
85         private bool _isBusy=true;
86
87         public ObservableCollection<ObjectInfo> Checks
88         {
89             get { return _checks; }
90         }
91
92         public void GetChecks()
93         {
94             var root = RootNodes[0];            
95             _checks = new ObservableCollection<ObjectInfo>(
96                 from record in root
97                 where record.IsChecked==true
98                 select record.ObjectInfo);
99             NotifyOfPropertyChange(() => Checks);
100         }
101
102         public SelectiveSynchViewModel(PithosMonitor monitor, IEventAggregator events, AccountSettings account)
103         {
104             Account = account;
105             AccountName = account.AccountName;
106             Title = account.AccountName;
107             _monitor = monitor;
108             _events = events;
109             TaskEx.Run(LoadRootNode);
110         }
111
112         private void LoadRootNode()
113         {
114             var client = _monitor.CloudClient;
115
116             var dirs = from container in client.ListContainers(_monitor.UserName)
117                        select new DirectoryRecord
118                                   {
119                                       DisplayName = container.Name,
120                                       Uri=new Uri(client.StorageUrl,container.Name),
121                                       Directories = (from dir in client.ListObjects(_monitor.UserName, container.Name, "")
122                                                      where dir.Content_Type == DirectoryType
123                                                      select new DirectoryRecord { DisplayName = dir.Name, ObjectInfo = dir }).ToList()
124                                   };
125             var ownFolders = dirs.ToList();
126
127             var accounts = client.ListSharingAccounts();
128
129             var accountNodes=from account in client.ListSharingAccounts()
130                              select new DirectoryRecord
131                              {
132                                 DisplayName=account.name,
133                                 Directories=(from container in client.ListContainers(account.name)
134                                             select new DirectoryRecord
135                                                         {
136                                                             DisplayName=container.Name,
137                                                             Directories=(from folder in client.ListObjects(account.name,container.Name,"")
138                                                                         where folder.Content_Type==DirectoryType
139                                                                         select new DirectoryRecord{DisplayName=folder.Name,ObjectInfo=folder}).ToList()
140                                                         }).ToList()
141                              };                                                          
142
143             var othersNode = new DirectoryRecord
144                                  {
145                                      DisplayName = "Others",
146                                      Directories=accountNodes.ToList()
147                                  };
148
149             
150             var rootItem = new DirectoryRecord
151                                {
152                                    DisplayName = AccountName ,
153                                    Directories = ownFolders.ToList()
154                                };
155
156             Execute.OnUIThread(() =>
157                                    {
158                                        this.RootNodes.Add(rootItem);
159                                        this.RootNodes.Add(othersNode);
160                                    });
161
162             SetInitialSelections(Account);
163             
164             IsBusy = false;
165         }
166
167         public bool IsBusy
168         {
169             get {
170                 return _isBusy;
171             }
172             set {
173                 _isBusy = value;
174                 NotifyOfPropertyChange(()=>IsBusy);
175             }
176         }
177
178         private void SetInitialSelections(AccountSettings account)
179         {
180             var selections = account.SelectiveFolders;
181
182             if (selections.Count == 0)
183                 return;
184             //Initially, all nodes are checked
185             //We need to *uncheck* the nodes that are not selected
186
187             var selects = from rootRecord in RootNodes
188                           from record in rootRecord
189                           where record.Uri !=null &&  !selections.Contains(record.Uri.ToString())
190                           select record;
191
192             selects.Apply(record=>record.IsChecked=false);
193         }
194
195         protected string AccountName { get; set; }
196
197         public void SaveChanges()
198         {
199             var uris = (from root in RootNodes
200                         from record in root
201                         where record.IsChecked == true && record.Uri != null
202                         select record.Uri).ToArray();            
203
204             SaveSettings(uris);
205             
206             //RootNodes is an ObservableCollection, it can't be enumerated iterativelly
207             
208             var added= (from root in RootNodes
209                         from record in root
210                          where record.Added && record.Uri != null
211                          select record.Uri).ToArray();
212             var removed = (from root in RootNodes
213                             from record in root
214                           where record.Removed && record.Uri != null
215                          select record.Uri).ToArray();
216             //TODO: Include Uris for the containers as well
217             _events.Publish(new SelectiveSynchChanges{Account=Account,Uris=uris,Added=added,Removed=removed});
218             
219
220             
221
222             TryClose(true);
223         }
224
225         
226         private void SaveSettings(IEnumerable<Uri> uris)
227         {
228             var selections = uris.Select(uri => uri.ToString()).ToArray();
229
230             Account.SelectiveFolders.Clear();
231             Account.SelectiveFolders.AddRange(selections);
232             Settings.Default.Save();            
233         }        
234
235         public void RejectChanges()
236         {
237             TryClose(false);
238         }
239     }
240 }