public static Topic TopicWithJObject(JObject json, FlickrGroup group)
        {
            // Get topic id
            string topicId = json["id"].ToString();
            Topic topic = null;
            if (group.TopicCache.ContainsKey(topicId))
            {
                topic = group.TopicCache[topicId];
            }
            else
            {
                topic = new Topic();
                topic.ResourceId = topicId;
                group.TopicCache[topicId] = topic;
            }

            // Parse user
            topic.Author = UserFactory.UserWithTopicJObject(json);
            topic.IsAdmin = (json["role"].ToString() == "admin");
            topic.CreationDate = json["datecreate"].ToString().ToDateTime();

            // Subject
            topic.Subject = json["subject"].ToString();

            // Message
            topic.Message = json["message"]["_content"].ToString();

            // Replies
            topic.CanReply = (json["can_reply"].ToString() == "1");
            topic.LastReplyDate = json["datelastpost"].ToString().ToDateTime();
            topic.ReplyCount = int.Parse(json["count_replies"].ToString());

            return topic;
        }
        // Constructor
        public GroupAddPhotoView(FlickrGroup groupSource)
        {
            InitializeComponent();

            Group = groupSource;

            // Initialize data providers
            PhotoCollection = new ObservableCollection<SelectablePhoto>();
            PhotoListView.ItemsSource = PhotoCollection;

            // Renderers
            PhotoPickerRenderer.CanSelect = true;

            // Events
            Cinderella.CinderellaCore.GroupInfoUpdated += OnGroupInfoReturned;
            Cinderella.CinderellaCore.PhotoStreamUpdated += OnPhotoStreamUpdated;

            Cinderella.CinderellaCore.AddPhotoToGroupCompleted += OnAddPhotoCompleted;
            Anaconda.AnacondaCore.AddPhotoToGroupException += OnAddPhotoException;

            Cinderella.CinderellaCore.RemovePhotoFromGroupCompleted += OnRemovePhotoCompleted;
            Anaconda.AnacondaCore.RemovePhotoFromGroupException += OnRemovePhotoException;

            PhotoPickerRenderer.SelectionChanged += OnPhotoPickerToggled;

            // Get group info
            StatusLabel.Text = AppResources.GroupRetrievingInfoText;
            StatusProgressBar.Visibility = Visibility.Visible;
            Anaconda.AnacondaCore.GetGroupInfoAsync(groupSource.ResourceId);
        }
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);

            string groupId = NavigationContext.QueryString["group_id"];
            group = Cinderella.CinderellaCore.GroupCache[groupId];

            string topicId = NavigationContext.QueryString["topic_id"];
            topic = group.TopicCache[topicId];

            // Reply list
            ReplyCollection = new ObservableCollection<ModelBase>();
            ReplyListView.ItemsSource = ReplyCollection;

            // Add topic as first item
            ReplyCollection.Add(topic);

            foreach (var reply in topic.Replies)
            {
                ReplyCollection.Add(reply);
            }

            // Config app bar
            ApplicationBar = Resources["ReplyListAppBar"] as ApplicationBar;

            // Events
            Cinderella.CinderellaCore.TopicRepliesUpdated += OnRepliesUpdated;
            Anaconda.AnacondaCore.AddTopicReplyException += OnAddReplyException;
            Cinderella.CinderellaCore.AddTopicReplyCompleted += OnAddReplyComplete;

            SystemTray.ProgressIndicator = new ProgressIndicator();
            SystemTray.ProgressIndicator.IsIndeterminate = true;
            SystemTray.ProgressIndicator.Text = AppResources.DiscussionRetrievingRepliesText;
            SystemTray.ProgressIndicator.IsVisible = true;

            // Refresh reply list
            Anaconda.AnacondaCore.GetTopicRepliesAsync(topicId, groupId, new Dictionary<string, string> { { "page", "1" }, { "per_page", Anaconda.DefaultItemsPerPage.ToString() } });
        }
        public static FlickrGroup GroupWithJObject(JObject json)
        {
            FlickrGroup group = null;

            // Get group id
            string groupId;
            JToken nsidValue;
            if (json.TryGetValue("nsid", out nsidValue))
            {
                groupId = json["nsid"].ToString();
            }
            else
            {
                groupId = json["id"].ToString();
            }

            if (Cinderella.CinderellaCore.GroupCache.ContainsKey(groupId))
                group = Cinderella.CinderellaCore.GroupCache[groupId];
            else
            {
                group = new FlickrGroup();
                group.ResourceId = groupId;
                Cinderella.CinderellaCore.GroupCache[group.ResourceId] = group;
            }

            group.Farm = json["iconfarm"].ToString();
            group.Server = json["iconserver"].ToString();

            JToken nameValue;
            if (json.TryGetValue("name", out nameValue))
            {
                if (nameValue.GetType() == typeof(JValue))
                {
                    group.Name = json["name"].ToString();
                }
                else
                {
                    group.Name = json["name"]["_content"].ToString();
                }

            }

            JToken descValue;
            if (json.TryGetValue("description", out descValue))
            {
                if(descValue.GetType() == typeof(JValue))
                {
                    group.Description = json["description"].ToString();
                }
                else
                {
                    group.Description = json["description"]["_content"].ToString();
                }

            }

            // Is invitation_only
            JToken invitationValue;
            if(json.TryGetValue("invitation_only", out invitationValue)){
                group.IsInvitationOnly = (json["invitation_only"].ToString() == "1");
            }

            JToken rulesValue;
            if (json.TryGetValue("rules", out rulesValue))
            {
                group.Rules = json["rules"]["_content"].ToString();
            }

            JToken poolValue;
            if (json.TryGetValue("pool_count", out poolValue))
            {
                if(poolValue.GetType() == typeof(JValue))
                    group.PhotoCount = int.Parse(json["pool_count"].ToString());
                else
                    group.PhotoCount = int.Parse(json["pool_count"]["_content"].ToString());
            }

            JToken topicValue;
            if (json.TryGetValue("topic_count", out topicValue))
            {
                if (topicValue.GetType() == typeof(JValue))
                    group.TopicCount = int.Parse(json["topic_count"].ToString());
                else
                    group.TopicCount = int.Parse(json["topic_count"]["_content"].ToString());
            }

            JToken membersValue;
            if (json.TryGetValue("members", out membersValue))
            {
                if (membersValue.GetType() == typeof(JValue))
                    group.MemberCount = int.Parse(json["members"].ToString());

                else
                    group.MemberCount = int.Parse(json["members"]["_content"].ToString());
            }

            JToken privacyValue;
            if (json.TryGetValue("privacy", out privacyValue))
            {
                int privacyId = int.Parse(json["privacy"]["_content"].ToString());
                group.Privacy = (FlickrGroupPrivicy)privacyId;
            }

            JToken throttleValue;
            if (json.TryGetValue("throttle", out throttleValue))
            {
                JObject throttleObject = (JObject)json["throttle"];

                JToken modeValue;
                if(throttleObject.TryGetValue("mode", out modeValue))
                {
                    group.ThrottleMode = json["throttle"]["mode"].ToString();
                }

                JToken countValue;
                if(throttleObject.TryGetValue("count", out countValue))
                {
                    group.ThrottleMaxCount = int.Parse(json["throttle"]["count"].ToString());
                }

                JToken remainingValue;
                if (throttleObject.TryGetValue("remaining", out remainingValue))
                {
                    group.ThrottleRemainingCount = int.Parse(json["throttle"]["remaining"].ToString());
                }
            }

            return group;
        }
        public void OnPopupRemoved()
        {
            if (eventListenersRemoved)
                return;

            eventListenersRemoved = true;

            Cinderella.CinderellaCore.GroupInfoUpdated -= OnGroupInfoReturned;
            Cinderella.CinderellaCore.PhotoStreamUpdated -= OnPhotoStreamUpdated;

            Cinderella.CinderellaCore.AddPhotoToGroupCompleted -= OnAddPhotoCompleted;
            Anaconda.AnacondaCore.AddPhotoToGroupException -= OnAddPhotoException;

            Cinderella.CinderellaCore.RemovePhotoFromGroupCompleted -= OnRemovePhotoCompleted;
            Anaconda.AnacondaCore.RemovePhotoFromGroupException -= OnRemovePhotoException;

            PhotoPickerRenderer.SelectionChanged -= OnPhotoPickerToggled;

            PhotoListView.ItemsSource = null;
            PhotoCollection.Clear();
            PhotoCollection = null;

            Group = null;
            SelectedPhotos.Clear();
            SelectedPhotos = null;
        }
        private void PerformAppearanceAnimation()
        {
            double h = System.Windows.Application.Current.Host.Content.ActualHeight;

            CompositeTransform ct = (CompositeTransform)LayoutRoot.RenderTransform;
            ct.TranslateY = h;

            LayoutRoot.Visibility = Visibility.Visible;

            Storyboard animation = new Storyboard();
            animation.Duration = new Duration(TimeSpan.FromSeconds(0.3));

            // Y animation
            DoubleAnimation galleryAnimation = new DoubleAnimation();
            galleryAnimation.Duration = new Duration(TimeSpan.FromSeconds(0.3));
            galleryAnimation.To = 0.0;
            galleryAnimation.EasingFunction = new CubicEase() { EasingMode = EasingMode.EaseOut };
            Storyboard.SetTarget(galleryAnimation, LayoutRoot);
            Storyboard.SetTargetProperty(galleryAnimation, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.TranslateY)"));
            animation.Children.Add(galleryAnimation);
            animation.Begin();
            animation.Completed += (sender, e) =>
            {
                string groupId = NavigationContext.QueryString["group_id"];

                if (Cinderella.CinderellaCore.GroupCache.ContainsKey(groupId))
                {
                    this.GroupSource = Cinderella.CinderellaCore.GroupCache[groupId];
                    this.DataContext = GroupSource;

                    // Config app bar
                    ApplicationBar = Resources["PhotoPageAppBar"] as ApplicationBar;
                }
            };
        }
        protected override void OnRemovedFromJournal(JournalEntryRemovedEventArgs e)
        {
            Anaconda.AnacondaCore.AddTopicException -= OnAddTopicException;
            Cinderella.CinderellaCore.AddTopicCompleted -= OnAddTopicComplete;

            Cinderella.CinderellaCore.GroupPhotoListUpdated -= OnPhotoListUpdated;

            Cinderella.CinderellaCore.GroupTopicsUpdated -= OnTopicListUpdated;

            PhotoPageView.RemoveEventListeners();
            TopicPageView.RemoveEventListeners();

            GroupSource = null;

            base.OnRemovedFromJournal(e);
        }
        protected override void OnRemovedFromJournal(JournalEntryRemovedEventArgs e)
        {
            Cinderella.CinderellaCore.TopicRepliesUpdated -= OnRepliesUpdated;
            Anaconda.AnacondaCore.AddTopicReplyException -= OnAddReplyException;
            Cinderella.CinderellaCore.AddTopicReplyCompleted -= OnAddReplyComplete;

            group = null;
            ReplyListView.ItemsSource = null;
            ReplyCollection.Clear();

            base.OnRemovedFromJournal(e);
        }