public FileSearchResult(FileSearchResult previous,
                                FileSegmentSearch current,
                                FileInfo info,
                                Encoding encoding,
                                int limit)
        {
            Maximum    = limit;
            LastSearch = current;
            Info       = info;
            Encoding   = encoding;

            _allSearches = previous._allSearches.Values.ToDictionary(fss => fss.Key);

            var lastTail = _allSearches.Lookup(FileSegmentKey.Tail);

            if (current.Segment.Type == FileSegmentType.Tail)
            {
                TailInfo = lastTail.HasValue
                            ? new TailInfo(lastTail.Value.Segment.End)
                            : new TailInfo(current.Segment.End);
            }
            else
            {
                TailInfo = lastTail.HasValue
                            ? previous.TailInfo
                            : TailInfo.None;
            }

            _allSearches[current.Key] = current;
            var all = _allSearches.Values.ToArray();

            IsSearching       = all.Any(s => s.Segment.Type == FileSegmentType.Head && s.Status != FileSegmentSearchStatus.Complete);
            Segments          = all.Length;
            SegmentsCompleted = all.Count(s => s.Segment.Type == FileSegmentType.Head && s.Status == FileSegmentSearchStatus.Complete);
            Size = all.Last().Segment.End;

            //For large sets this could be very inefficient
            Matches         = all.SelectMany(s => s.Lines).OrderBy(l => l).ToArray();
            HasReachedLimit = Matches.Length >= limit;
        }
        public FileSearchResult(FileSegmentSearch initial,
                                FileInfo info,
                                Encoding encoding,
                                int limit)
        {
            Info         = info;
            Encoding     = encoding;
            LastSearch   = initial;
            _allSearches = new Dictionary <FileSegmentKey, FileSegmentSearch>
            {
                [initial.Key] = initial
            };

            IsSearching       = initial.Status != FileSegmentSearchStatus.Complete;
            Segments          = 1;
            SegmentsCompleted = IsSearching ? 0 : 1;
            Matches           = initial.Lines.ToArray();
            TailInfo          = TailInfo.None;
            Size            = 0;
            Maximum         = limit;
            HasReachedLimit = false;
        }
        public FileSearchResult(FileSearchResult previous,
                                FileSegmentSearch current,
                                FileInfo info,
                                Encoding encoding,
                                int limit)
        {
            Maximum    = limit;
            LastSearch = current;
            Info       = info;
            Encoding   = encoding;

            _allSearches = previous._allSearches.Values.ToDictionary(fss => fss.Key);

            var lastTail = _allSearches.Lookup(FileSegmentKey.Tail);

            if (current.Segment.Type == FileSegmentType.Tail)
            {
                TailInfo = lastTail.HasValue
                    ? new TailInfo(lastTail.Value.Segment.End)
                    : new TailInfo(current.Segment.End);
            }
            else
            {
                TailInfo = lastTail.HasValue
                    ? previous.TailInfo
                    : TailInfo.None;
            }

            _allSearches[current.Key] = current;
            var all = _allSearches.Values.ToArray();

            IsSearching =
                all.Any(s => s.Segment.Type == FileSegmentType.Head && s.Status != FileSegmentSearchStatus.Complete);
            Segments          = all.Length;
            SegmentsCompleted =
                all.Count(s => s.Segment.Type == FileSegmentType.Head && s.Status == FileSegmentSearchStatus.Complete);
            Size = all.Last().Segment.End;

            //For large sets this could be very inefficient
            Matches         = all.SelectMany(s => s.Lines).OrderBy(l => l).ToArray();
            HasReachedLimit = Matches.Length >= limit;

            //skip the same file in here, because we do not want to store in the list.
            if (previous.Info.FullName != info.FullName)
            {
                var prevPointer = previous;
                //seek to the end of the linked list
                while (prevPointer?.Next != null)
                {
                    prevPointer = prevPointer.Next as FileSearchResult;
                }
                var lastPrevPointer = default(FileSearchResult);
                //find the modified file and replace from the list
                while (prevPointer != null)
                {
                    if (prevPointer.Info.FullName == Info.FullName && prevPointer.Count != Count)
                    {
                        Next     = prevPointer.Next;
                        Previous = prevPointer.Previous;
                        if (lastPrevPointer != null)
                        {
                            lastPrevPointer.Previous = this;
                        }
                        prevPointer.Previous     = null;
                        prevPointer.Next         = null;
                        NumberOfPreviousProvider = prevPointer.NumberOfPreviousProvider;
                        return;
                    }
                    lastPrevPointer = prevPointer;
                    prevPointer     = prevPointer.Previous as FileSearchResult;
                }

                //build the linked list in here
                Previous                 = previous;
                previous.Next            = this;
                NumberOfPreviousProvider = previous.NumberOfPreviousProvider + 1;
            }
        }