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