/// <summary>
        /// Get the <see cref="HighlightedItem"/> for the current text, taking into account Find mode etc
        /// </summary>
        /// <param name="line">The line of text to pattern match</param>
        /// <returns>A <see cref="HighlightedItem"/></returns>
        private HighlightedItem GetHighlighting(string line)
        {
            HighlightedItem item = null;

            item = this.GetHighlightedItem(line);

            if (item == null)
            {
                throw new Exception("Item cannot be null!");
            }

            return(item);
        }
        private void UpdateFindHighlighting(string text)
        {
            this.Dispatcher.Invoke((Action)(() =>
            {
                foreach (int i in this.PreviouslySelectedItems)
                {
                    this.colourfulListView.SelectedIndex = -1;
                    HighlightedItem item = new HighlightedItem(((HighlightedItem)this.colourfulListView.Items[i]).Text, ((HighlightedItem)this.colourfulListView.Items[i]).ForeColour, ((HighlightedItem)this.colourfulListView.Items[i]).BackColour);
                    item.Selected = false;
                    this.colourfulListView.Items[i] = item;
                }

                for (int i = LastSearchIndex; i < this.colourfulListView.Items.Count; i++)
                {
                    HighlightedItem item = new HighlightedItem(((HighlightedItem)this.colourfulListView.Items[i]).Text, ((HighlightedItem)this.colourfulListView.Items[i]).ForeColour, ((HighlightedItem)this.colourfulListView.Items[i]).BackColour);
                    if (this.GetFoundHighlightItem(ref item))
                    {
                        {
                            this.colourfulListView.Items[i] = item;
                            this.colourfulListView.SelectedIndex = i;
                            this.colourfulListView.ScrollIntoView(item);
                        }

                        LastSearchIndex = i + 1;

                        this.previouslySelectedItems = new List <int>();
                        this.previouslySelectedItems.Add(i);

                        return;
                    }
                    else
                    {
                        //HACK: need to ensure that blank lines are not null!
                        if (item != null)
                        {
                            item.Selected = false;
                            this.colourfulListView.Items[i] = item;
                            this.colourfulListView.SelectedIndex = -1;
                        }
                    }
                }


                // We've not found anything, since the last find
                LastSearchIndex = 0;
                ThrowFindFinished();
            }));
        }
        /// <summary>
        /// Gets the <see cref="HighlightedItem"/> for the given text once it has either been searched for and found or pattern matched
        /// </summary>
        /// <param name="text">The line of text to find/pattern match</param>
        private HighlightedItem GetHighlightedItem(string text)
        {
            HighlightedItem highlighted = new HighlightedItem();

            highlighted.Text = text;

            highlighted.ForeColour = Constants.DEFAULT_FORECOLOUR;
            highlighted.BackColour = Constants.DEFAULT_BACKCOLOUR;

            foreach (HighlightItem highlight in FindFirstHighlightByText(this.Patterns, text))
            {
                if (highlight.BorderColour != Constants.DEFAULT_NULL_COLOUR)
                {
                    highlighted.ForeColour   = Constants.DEFAULT_FORECOLOUR;
                    highlighted.BackColour   = Constants.DEFAULT_BACKCOLOUR;
                    highlighted.BorderColour = highlight.BorderColour;
                }
                else
                {
                    highlighted.ForeColour   = highlight.ForeColour;
                    highlighted.BackColour   = highlight.BackColour;
                    highlighted.BorderColour = Constants.DEFAULT_NULL_COLOUR;
                }

                // Only play a sound if we are told to by ReadLines() and the user
                if (SettingsHelper.AppSettings[AppSettings.PLAY_SOUND] != null && PlaySound && bool.Parse(SettingsHelper.AppSettings[AppSettings.PLAY_SOUND]))
                {
                    AudioHelper.Play(SettingsHelper.AppSettings[AppSettings.PLAY_SOUND_FILE]);
                    SoundPlayed = true;
                }

                if ((SettingsHelper.AppSettings[AppSettings.PAUSE_ON_FOUND] != null && bool.Parse(SettingsHelper.AppSettings[AppSettings.PAUSE_ON_FOUND])) || this.IsStopFollowTail)
                {
                    IsFollowTail = false;
                }

                break; // use the first one we come across in the list - items at the top are most important
            }

            return(highlighted);
        }
        /// <summary>
        /// Gets the highlight item of a found piece of text
        /// </summary>
        /// <param name="line">The line of text to match</param>
        /// <returns></returns>
        private bool GetFoundHighlightItem(ref HighlightedItem item)
        {
            HighlightItem special = new HighlightItem(this.SearchText, Constants.DEFAULT_FORECOLOUR, Constants.DEFAULT_BACKCOLOUR);

            if (!string.IsNullOrEmpty(special.Pattern) && !string.IsNullOrEmpty(item.Text))
            {
                if (item.Text == special.Pattern || _patternMatching.MatchPattern(item.Text, special.Pattern))
                {
                    item.Selected = true;

                    return(true);
                }
                else
                {
                    item.Selected = false;

                    return(false);
                }
            }

            return(false);
        }
        /// <summary>
        /// Add items to the view collection when the file is updated
        /// </summary>
        private int AddHightLightedItem(string line, int location)
        {
            return((int)this.Dispatcher.Invoke((ReturnInt)(() =>
            {
                int index = location;
                HighlightedItem item = GetHighlighting(line);

                if (location >= this.colourfulListView.Items.Count || location == -1)
                {
                    this.CollectionBackBuffer.Add(item);

                    return this.CollectionBackBuffer.Count - 1;
                }
                else
                {
                    this.CollectionBackBuffer.RemoveAt(index);
                    this.CollectionBackBuffer.Insert(index, item);

                    return index;
                }
            })));
        }
        private bool ReadLines(bool overrideFileReadyCheck)
        {
            lock (this)
            {
                if (overrideFileReadyCheck || this.IsFileReadyForReread())
                {
                    //using (StreamReader streamReader = this.OpenFile())
                    using (StreamReader streamReader = new StreamReader(this.OpenFile()))
                    {
                        // If there is no stream, or it's empty reset the collection and return
                        if (streamReader == null || streamReader.BaseStream.Length == 0)
                        {
                            this.LastReadStream = new MemoryStream();
                            this.CollectionBackBuffer.Clear();
                            CopyBackBufferToFront();

                            return(false);
                        }

                        // We have a viable stream so we now must parse through it
                        StreamReader oldReader = new StreamReader(this.LastReadStream);
                        oldReader.BaseStream.Position = 0;
                        int  location        = 0;
                        int  positionInList  = 0;
                        bool skipSameContent = false;
                        int  lastUsedIndex   = 0;
                        this.SoundPlayed = false;
                        this.PlaySound   = true;

                        while (streamReader.Peek() > -1)
                        {
                            string oldLine = oldReader.ReadLine();
                            string line    = streamReader.ReadLine();

                            if (line != null)
                            {
                                // There is no previous stream to compare against so just add the content to the screen
                                if (oldReader.BaseStream.Length <= 0)
                                {
                                    this.SoundPlayed = true;
                                    skipSameContent  = false;
                                    positionInList   = location;
                                }
                                else
                                {
                                    // We have more lines in the new stream than the old so add it to the end of the collection
                                    if (oldLine == null)
                                    {
                                        // This results in a blank line being added to the end of the line collection
                                        positionInList = -1;
                                    }

                                    // the oldline is not null and is either different from the new line or empty so add it to the collection
                                    // at the current location
                                    else if ((oldLine != null) && (!line.Equals(oldLine) || oldLine == string.Empty))
                                    {
                                        positionInList = location;
                                    }

                                    // Otherwise the old and new lines are the same so do nothing to the screen content
                                    else
                                    {
                                        this.PlaySound  = false;
                                        skipSameContent = true;
                                        lastUsedIndex   = location;
                                        HighlightedItem item = GetHighlighting(line);
                                        this.CollectionBackBuffer[location].BackColour = item.BackColour;
                                        this.CollectionBackBuffer[location].ForeColour = item.ForeColour;
                                        this.PlaySound = true;
                                    }
                                }

                                // if the old and new lines are different
                                if (!skipSameContent)
                                {
                                    line          = line.TrimEnd(Constants.NULL_TERMINATOR).Replace(Constants.MAC_NEWLINE, Constants.CARRIAGE_RETURN).Replace(Constants.UNIX_NEWLINE, Constants.LINE_FEED); // in case of incorrectly selected line end;
                                    lastUsedIndex = this.AddHightLightedItem(line, positionInList);

                                    if (this.SoundPlayed)
                                    {
                                        this.PlaySound = false;
                                    }
                                }

                                skipSameContent = false;
                            }

                            location++;

                            if (location % 1000 == 0)
                            {
                                ReportProgress((int)(location * 100 / streamReader.BaseStream.Length), string.Format(LanguageHelper.GetLocalisedText((Application.Current as IApplication), Constants.LINES_IN_FILE), location), false, System.Windows.Visibility.Visible);
                            }
                        }

                        // if the lastUsedIndex has not been set above then
                        // default it to the location
                        if (lastUsedIndex == 0)
                        {
                            lastUsedIndex = location;
                        }

                        // Remove any lines that have been deleted from the end of the file
                        int max = this.CollectionBackBuffer.Count - 1;

                        if (lastUsedIndex != max)
                        {
                            for (int j = max; j > lastUsedIndex; j--)
                            {
                                this.RemoveHightlightedItem(j);
                            }
                        }

                        // Create the previous stream to compare with next time from the current stream this time
                        streamReader.BaseStream.Position = 0;
                        this.LastReadStream = new MemoryStream();
                        streamReader.BaseStream.CopyTo(this.LastReadStream);
                    }

                    // Copy the collection of ListView items to the ListView control
                    // Doing it this way should result in quicker page refreshes as the screen will only be updated once
                    CopyBackBufferToFront();

                    return(true);
                }
            }

            return(false);
        }
        private void UpdateFindHighlighting(string text)
        {
            this.Dispatcher.Invoke((Action)(() =>
                        {
                            foreach (int i in this.PreviouslySelectedItems)
                            {
                                this.colourfulListView.SelectedIndex = -1;
                                HighlightedItem item = new HighlightedItem(((HighlightedItem)this.colourfulListView.Items[i]).Text, ((HighlightedItem)this.colourfulListView.Items[i]).ForeColour, ((HighlightedItem)this.colourfulListView.Items[i]).BackColour);
                                item.Selected = false;
                                this.colourfulListView.Items[i] = item;
                            }

                            for (int i = LastSearchIndex; i < this.colourfulListView.Items.Count; i++)
                            {
                                HighlightedItem item = new HighlightedItem(((HighlightedItem)this.colourfulListView.Items[i]).Text, ((HighlightedItem)this.colourfulListView.Items[i]).ForeColour, ((HighlightedItem)this.colourfulListView.Items[i]).BackColour);
                                if (this.GetFoundHighlightItem(ref item))
                                {
                                    {
                                        this.colourfulListView.Items[i] = item;
                                        this.colourfulListView.SelectedIndex = i;
                                        this.colourfulListView.ScrollIntoView(item);
                                    }

                                    LastSearchIndex = i + 1;

                                    this.previouslySelectedItems = new List<int>();
                                    this.previouslySelectedItems.Add(i);

                                    return;
                                }
                                else
                                {
                                    //HACK: need to ensure that blank lines are not null!
                                    if (item != null)
                                    {
                                        item.Selected = false;
                                        this.colourfulListView.Items[i] = item;
                                        this.colourfulListView.SelectedIndex = -1;
                                    }
                                }
                            }

                            // We've not found anything, since the last find
                            LastSearchIndex = 0;
                            ThrowFindFinished();

                        }));
        }
        /// <summary>
        /// Gets the <see cref="HighlightedItem"/> for the given text once it has either been searched for and found or pattern matched
        /// </summary>
        /// <param name="text">The line of text to find/pattern match</param>
        private HighlightedItem GetHighlightedItem(string text)
        {
            HighlightedItem highlighted = new HighlightedItem();
            highlighted.Text = text;

            highlighted.ForeColour = Constants.DEFAULT_FORECOLOUR;
            highlighted.BackColour = Constants.DEFAULT_BACKCOLOUR;

            foreach (HighlightItem highlight in FindFirstHighlightByText(this.Patterns, text))
            {
                if (highlight.BorderColour != Constants.DEFAULT_NULL_COLOUR)
                {
                    highlighted.ForeColour = Constants.DEFAULT_FORECOLOUR;
                    highlighted.BackColour = Constants.DEFAULT_BACKCOLOUR;
                    highlighted.BorderColour = highlight.BorderColour;
                }
                else
                {
                    highlighted.ForeColour = highlight.ForeColour;
                    highlighted.BackColour = highlight.BackColour;
                    highlighted.BorderColour = Constants.DEFAULT_NULL_COLOUR;
                }

                // Only play a sound if we are told to by ReadLines() and the user
                if (SettingsHelper.AppSettings[AppSettings.PLAY_SOUND] != null && PlaySound && bool.Parse(SettingsHelper.AppSettings[AppSettings.PLAY_SOUND]))
                {
                    AudioHelper.Play(SettingsHelper.AppSettings[AppSettings.PLAY_SOUND_FILE]);
                    SoundPlayed = true;
                }

                if ((SettingsHelper.AppSettings[AppSettings.PAUSE_ON_FOUND] != null && bool.Parse(SettingsHelper.AppSettings[AppSettings.PAUSE_ON_FOUND])) || this.IsStopFollowTail)
                {
                    IsFollowTail = false;
                }

                break; // use the first one we come across in the list - items at the top are most important
            }

            return highlighted;
        }
        /// <summary>
        /// Gets the highlight item of a found piece of text
        /// </summary>
        /// <param name="line">The line of text to match</param>
        /// <returns></returns>
        private bool GetFoundHighlightItem(ref HighlightedItem item)
        {
            HighlightItem special = new HighlightItem(this.SearchText, Constants.DEFAULT_FORECOLOUR, Constants.DEFAULT_BACKCOLOUR);

            if (!string.IsNullOrEmpty(special.Pattern) && !string.IsNullOrEmpty(item.Text))
            {
                if (item.Text == special.Pattern || _patternMatching.MatchPattern(item.Text, special.Pattern))
                {
                    item.Selected = true;

                    return true;
                }
                else
                {
                    item.Selected = false;

                    return false;
                }
            }

            return false;
        }