/// <summary>
        /// Convert a Post (used for the database) in a WPost (used for the web).
        /// </summary>
        /// <param name="db">Database connector data context.</param>
        /// <param name="user">User that requires the conversion.</param>
        /// <param name="post">The Post to convert.</param>
        /// <returns>A WPost.</returns>
        public static WPost PostToWPost(ConnectorDataContext db, User user, Post post)
        {
            WUser author = Converter.UserToWUser(db, user, post.ChosenFeature.Registration.User, false);

            WService service = Converter.ServiceInstanceToWService(db, user, post.ChosenFeature.Registration.ServiceInstance, false);

            WPost result = new WPost()
            {
                Id = post.id,
                User = author,
                Service = service,
                Message = post.message,
                CreateAt = post.createAt
            };

            return result;
        }
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="post">Post to be showed by this interface.</param>
        internal UIPost(WPost post, Boolean enableProfileRedirect)
        {
            Contract.Requires(post != null);

            InitializeComponent();
            _post = post;
            _enableProfileRedirect = enableProfileRedirect;

            if (String.IsNullOrEmpty(_post.User.Avatar))
                AvatarImage.InternalImage.Source = new BitmapImage(new Uri("pack://*****:*****@"http"))
                {
                    //last element of words array is always "http:/…"
                    if (!words[i].Equals("http:/…"))
                    {
                        Hyperlink hyperlink = new Hyperlink();
                        hyperlink.Inlines.Add(words[i]);
                        hyperlink.NavigateUri = new Uri(words[i]);
                        hyperlink.ToolTip = ("Go to: " + words[i]);
                        hyperlink.Click += hyperlink_Click;
                        ContextMenu contextMenu = new ContextMenu();
                        MenuItemWithLink internalBrowser = new MenuItemWithLink();
                        internalBrowser.hyperlink = hyperlink;
                        internalBrowser.Header = "Internal Browser";
                        internalBrowser.Click += internalBrowser_Click;
                        MenuItemWithLink externalBrowser = new MenuItemWithLink();
                        externalBrowser.hyperlink = hyperlink;
                        externalBrowser.Header = "External Browser";
                        externalBrowser.Click += externalBrowser_Click;
                        contextMenu.Items.Add(internalBrowser);
                        contextMenu.Items.Add(externalBrowser);
                        hyperlink.ContextMenu = contextMenu;
                        TextTextBlock.Inlines.Add(hyperlink);
                        TextTextBlock.Inlines.Add(" ");
                    }
                    string link = words[i];

                    ThreadStart starter = delegate
                    {
                        try
                        {
                            checkMediaContent(link);
                        }
                        catch (Exception ex)
                        {
                            log.Error(ex.Message, ex);
                        }
                    };

                    Thread previewThread = new Thread(starter);
                    previewThread.Name = "Preview";
                    previewThread.Start();
                }
                else
                {
                    TextTextBlock.Inlines.Add(words[i]);
                    TextTextBlock.Inlines.Add(" ");
                }
            }

            TimeSpan difference = DateTime.UtcNow - _post.CreateAt;

            if (DateTime.Now.Hour < _post.CreateAt.Hour)
                difference += new TimeSpan(1, 0, 0, 0);

            if (difference.Days > 30)
                TimeSourceTextBlock.Text = "more than a month ago";
            else if (difference.Days > 1 && difference.Days <= 30)
                TimeSourceTextBlock.Text = "about " + difference.Days + " days ago";
            else if (difference.Days == 1)
                TimeSourceTextBlock.Text = "about a day ago";
            else
            {
                if (difference.Hours > 1)
                    TimeSourceTextBlock.Text = "about " + difference.Hours + " hours ago";
                else if (difference.Hours == 1)
                    TimeSourceTextBlock.Text = "about an hour ago";
                else
                {
                    if (difference.Minutes > 1)
                        TimeSourceTextBlock.Text = "about " + difference.Minutes + " minutes ago";
                    else if (difference.Minutes == 1)
                        TimeSourceTextBlock.Text = "about a minute ago";
                    else
                        TimeSourceTextBlock.Text = "a few seconds ago";
                }
            }

            TimeSourceTextBlock.Text += " from " + _post.Service.Name;
        }
        private void UpdateTimeline()
        {
            lock (_lock)
            {
                while (true)
                {
                    WPost[] posts = new WPost[0];
                    Popups.UILoading loading = null;

                    if (_first == 0)
                    {
                        this.Dispatcher.BeginInvoke(new Action(delegate()
                        {
                            loading = new Popups.UILoading("Downloading posts");
                            UIController.ShowPanel(loading);
                        }));
                    }

                    switch (_timelineType)
                    {
                        case TimelineType.HomeTimeline:
                            posts = UIController.Proxy.GetHomeTimeline(UIController.MyProfile.Username, UIController.Password, _first);
                            break;
                        case TimelineType.PersonalTimeline:
                            posts = UIController.Proxy.GetUserTimeline(UIController.MyProfile.Username, UIController.Password, _owner.Username, _first);
                            break;
                        case TimelineType.DynamicTimeline:
                            posts = UIController.Proxy.GetIterationTimeline(UIController.MyProfile.Username, UIController.Password, _first);
                            break;
                        case TimelineType.InteractiveNetworkTimeline:
                            if (UIController.GetCurrentCollectionURL() != null)
                            {
                                Tuple<string, string> tempObject = UIController.GetActiveObject();
                                if (tempObject != null)
                                {
                                    if (tempObject.Item1 != _interactiveObject.Item1 || tempObject.Item2 != _interactiveObject.Item2)
                                    {
                                        _first = 0;
                                        _last = 0;
                                        this.Dispatcher.BeginInvoke(new Action(delegate()
                                            {
                                                UIController.HidePanel(loading);
                                                TimelineStackPanel.Children.Clear();
                                                loading = new Popups.UILoading("Downloading posts");
                                                UIController.ShowPanel(loading);
                                            }));
                                        _interactiveObject = tempObject;
                                    }
                                    posts = UIController.Proxy.GetInteractiveTimeline(UIController.MyProfile.Username, UIController.Password, UIController.GetCurrentCollectionURL(), _interactiveObject.Item1, _interactiveObject.Item2, _first);

                                    // Reload timeline if document change during posts download
                                    tempObject = UIController.GetActiveObject();
                                    if (tempObject.Item1 != _interactiveObject.Item1 || tempObject.Item2 != _interactiveObject.Item2)
                                    {
                                        this.Dispatcher.BeginInvoke(new Action(delegate()
                                            {
                                                UIController.HidePanel(loading);
                                            }));
                                        continue;
                                    }
                                }
                            }
                            else
                            {
                                _first = 0;
                                _last = 0;
                                this.Dispatcher.BeginInvoke(new Action(delegate()
                                {
                                    //TODO Displays a message informing the user that needs to connect to a TFS collection
                                    TimelineStackPanel.Children.Clear();
                                }));
                            }
                            break;
                    }

                    this.Dispatcher.BeginInvoke(new Action(delegate()
                    {
                        if (posts.Length > 0)
                        {
                            _first = posts.First().Id;
                            if (_last == 0)
                                _last = posts.Last().Id;
                            for (int i = 0; i < posts.Length; i++)
                                if (_timelineType == TimelineType.PersonalTimeline)
                                    TimelineStackPanel.Children.Insert(i, new UIPost(posts[i], false));
                                else
                                    TimelineStackPanel.Children.Insert(i, new UIPost(posts[i], true));
                        }

                        UIController.HidePanel(loading);
                    }));

                    Monitor.Wait(_lock, new TimeSpan(0, 1, 0));
                }
            }
        }
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="post">Post to be showed by this interface.</param>
 internal UIPost(WPost post)
     : this(post, false)
 {
 }
        private void downloadOlderPosts()
        {
            WPost[] posts = new WPost[0];

            switch (_timelineType)
            {
                case TimelineType.HomeTimeline:
                    posts = UIController.Proxy.GetHomeTimeline(
                        UIController.MyProfile.Username, UIController.Password, 0, _last);
                    break;
                case TimelineType.PersonalTimeline:
                    posts = UIController.Proxy.GetUserTimeline(
                        UIController.MyProfile.Username, UIController.Password, _owner.Username, 0, _last);
                    break;
                case TimelineType.DynamicTimeline:
                    posts = UIController.Proxy.GetIterationTimeline(
                        UIController.MyProfile.Username, UIController.Password, 0, _last);
                    break;
                case TimelineType.InteractiveNetworkTimeline:
                    posts = UIController.Proxy.GetInteractiveTimeline(
                        UIController.MyProfile.Username, UIController.Password, UIController.GetCurrentCollectionURL(),
                        _interactiveObject.Item1, _interactiveObject.Item2, 0, _last);
                    break;
            }

            this.Dispatcher.BeginInvoke(new Action(delegate()
            {
                Busy.Visibility = Visibility.Hidden;
                if (posts.Length > 0)
                {
                    _last = posts.Last().Id;
                    foreach (WPost p in posts)
                        if (_timelineType == TimelineType.PersonalTimeline)
                            TimelineStackPanel.Children.Add(new UIPost(p, false));
                        else
                            TimelineStackPanel.Children.Add(new UIPost(p, true));
                    LoadingText.Visibility = Visibility.Hidden;
                }
                else
                {
                    LoadingText.Visibility = Visibility.Visible;
                    LoadingText.Text = "There are no older posts";
                }
                _olderPostAllowed = true;
            }));
        }