private IEnumerable <List <Comment> > EnumerateThreads(TreeNode <Comment> rootComment, LinkStorage <TreeNode <Comment> > ls)
        {
            HashSet <TreeNode <Comment> > wentThrough = new HashSet <TreeNode <Comment> >();

            // This enumerates all nodes.
            foreach (TreeNode <Comment> node in rootComment)
            {
                if (wentThrough.Contains(node))
                {
                    continue;
                }
                wentThrough.Add(node);

                List <Comment> thread = new List <Comment>();

                // First thread that starts from this node.
                Tuple <TreeNode <Comment>, TreeNode <Comment> > tuple = ls.GetLinksWithTop(node).FirstOrDefault();
                if (tuple != null)
                {
                    // OK, there is a link that starts from this node.

                    // First node.
                    AddCommentToList(thread, tuple.Item1);
                    while (tuple != null)
                    {
                        // Second node.
                        if (tuple.Item1 != tuple.Item2)
                        {
                            AddCommentToList(thread, tuple.Item2);
                            wentThrough.Add(tuple.Item2);
                        }

                        // Go deeper.
                        tuple = ls.GetLinksWithTop(tuple.Item2).Where(z => z.Item1 != z.Item2).FirstOrDefault();
                    }
                }
                else
                {
                    // There weren't any links starting from this one.
                    // Does any end on it?

                    tuple = ls.GetLinkWithBottom(node);

                    if (tuple != null)
                    {
                        thread.Add(tuple.Item2.Data);
                    }
                }

                // Save thread if not empty.
                if (thread.Count > 0)
                {
                    yield return(thread);
                }
            }

            yield break;
        }
        /// <summary>Goes through comment tree. If two links are adjacent and there are no others,
        /// add a missing link between them.</summary>
        /// <param name="tree">Comment tree.</param>
        /// <param name="ls">Links storage.</param>
        private void AddMissingLinksBetweenAdjacentOnes(TreeNode <Comment> tree, LinkStorage <TreeNode <Comment> > ls)
        {
            Tuple <TreeNode <Comment>, TreeNode <Comment> >[] allLinks = ls.EnumerateLinks().ToArray();

            foreach (var link in allLinks)
            {
                // Child node of (A - B), B.
                TreeNode <Comment> child = link.Item2;

                // Shouldn't have direct children. No (B - C) links.
                bool hasDirectChildren = ls.GetLinksWithTop(child).Where(z => z.Item1 != z.Item2).Any();
                if (hasDirectChildren)
                {
                    continue;
                }

                // First adjacent link, starting from C, (C - D).
                Tuple <TreeNode <Comment>, TreeNode <Comment> > singleAdjacentLink = child.Children.Select(ls.GetLinksWithTop).SelectMany(a => a).FirstOrDefault();
                if (singleAdjacentLink != null)
                {
                    // OK, create a link between (B - C).
                    // Now we have chain (A - B), (B - C), (C - D).
                    ls.AddLink(child, singleAdjacentLink.Item1);

                    // Is (A - B) actually (B - B)? If so, remove it.
                    if (link.Item1 == link.Item2)
                    {
                        ls.RemoveLink(link.Item1, link.Item2);
                    }
                }
            }
        }
        private void ReSetParentsForContinuousReplies(TreeNode <Comment> tree, LinkStorage <TreeNode <Comment> > ls)
        {
            var allLinksByParent = ls.EnumerateLinks().GroupBy(z => z.Item1);

            foreach (var group in allLinksByParent)
            {
                // (A - B), (A - C).
                Tuple <TreeNode <Comment>, TreeNode <Comment> >[] fromThis = group.ToArray();
                for (int i = 1; i < fromThis.Length; i++)
                {
                    // No (B - ...)?
                    bool previousHasOtherLinks = ls.GetLinksWithTop(fromThis[i - 1].Item2).Any();
                    if (previousHasOtherLinks)
                    {
                        continue;
                    }

                    // Then remove (A - C), set (B - C).
                    ls.RemoveLink(fromThis[i].Item1, fromThis[i].Item2);
                    ls.AddLink(fromThis[i - 1].Item2, fromThis[i].Item2);
                }
            }
        }