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