public Task<List<VisualBubble>> FetchNext()
            {
                return Task.Factory.StartNew<List<VisualBubble>>(() =>
                {
                    if (_endReached)
                        return null;

                    lock (BubbleGroupDatabase.OperationLock)
                    {
                        var groups = BubbleGroupManager.GetInner(_group);
                        var groupCursors = groups.Select(@group => new Tuple<BubbleGroup, long>(@group, -1)).ToList();

                        var allBubbles = new List<VisualBubble>();

                        var handles = OpenDatabaseStreams(groups).ToList();

                        GetMoreBubbles:

                        var result = LoadDatabaseBubblesOnUnitInto(groups, _day, handles, groupCursors, _selection.BubbleTypes, _selection.Comparer);

                        var bubbles = result.Item1;
                        if (bubbles != null)
                        {
                            allBubbles.AddRange(bubbles);
                        }

                        groupCursors = result.Item2;
                        _day++;

                        var endReached = result.Item2.Count(cursor => cursor.Item2 == -2);
                        if (endReached == result.Item2.Count)
                        {
                            _endReached = true;
                            goto ReturnResult;
                        }
                        if (bubbles == null)
                        {
                            goto GetMoreBubbles;
                        }
                        if (allBubbles.Count < 100)
                        {
                            goto GetMoreBubbles;
                        }

                        ReturnResult:

                        CloseDatabaseStreams(handles);

                        allBubbles.TimSort((x, y) => -x.Time.CompareTo(y.Time));

                        return allBubbles;
                    }
                });
            }
        private static void Populate(UnifiedBubbleGroup unified)
        {
            var innerGroupsCursors = unified.Groups.Select(@group => new Tuple<BubbleGroup, long>(@group, -1)).ToList();

            var allBubbles = new List<VisualBubble>();
            var day = 1;

            var handles = OpenDatabaseStreams(unified).ToList();

            GetMoreBubbles:
            var result = LoadDatabaseBubblesOnUnitInto(unified, day, handles, innerGroupsCursors);
            innerGroupsCursors = result.Item2;
            day++;
            var bubbles = result.Item1;
            if (bubbles != null)
            {
                allBubbles.AddRange(bubbles);
            }
            var endReached = result.Item2.Count(cursor => cursor.Item2 == -2);
            if (endReached == result.Item2.Count)
            {
                goto End;
            }
            if (bubbles == null)
            {
                goto GetMoreBubbles;
            }
            if (allBubbles.Count < 100)
            {
                goto GetMoreBubbles;
            }

            End:

            CloseDatabaseStreams(handles);

            allBubbles.TimSort((x, y) => x.Time.CompareTo(y.Time));
            Func<VisualBubble, VisualBubble> tryFindRealBubble = incoming =>
            {
                foreach (var bubble in
                    unified.Groups.SelectMany(@group => @group.Where(bubble => bubble.ID == incoming.ID)))
                {
                    return bubble;
                }

                return incoming;
            };
            for (var i = 0; i < allBubbles.Count; i++)
            {
                allBubbles[i] = tryFindRealBubble(allBubbles[i]);
            }
            unified.Bubbles.Clear();
            foreach (var bubble in allBubbles)
            {
                unified.Bubbles.Add(bubble);
            }
            unified.UnifiedGroupLoaded = true;
        }