# Copyright 2021 The Pigweed Authors
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.
"""LogView maintains a log pane's scrolling and searching state."""

from __future__ import annotations
import asyncio
import collections
import copy
from enum import Enum
import itertools
import logging
import operator
from pathlib import Path
import re
import time
from typing import Callable, Dict, List, Optional, Tuple, TYPE_CHECKING

from prompt_toolkit.data_structures import Point
from prompt_toolkit.formatted_text import StyleAndTextTuples

from pw_console.log_filter import (
    DEFAULT_SEARCH_MATCHER,
    LogFilter,
    RegexValidator,
    SearchMatcher,
    preprocess_search_regex,
)
from pw_console.log_screen import ScreenLine, LogScreen
from pw_console.log_store import LogStore
from pw_console.text_formatting import remove_formatting

if TYPE_CHECKING:
    from pw_console.console_app import ConsoleApp
    from pw_console.log_line import LogLine
    from pw_console.log_pane import LogPane

_LOG = logging.getLogger(__package__)


class FollowEvent(Enum):
    """Follow mode scroll event types."""
    SEARCH_MATCH = 'scroll_to_bottom'
    STICKY_FOLLOW = 'scroll_to_bottom_with_sticky_follow'


class LogView:
    """Viewing window into a LogStore."""

    # pylint: disable=too-many-instance-attributes,too-many-public-methods

    def __init__(
        self,
        log_pane: 'LogPane',
        application: 'ConsoleApp',
        log_store: Optional[LogStore] = None,
    ):
        # Parent LogPane reference. Updated by calling `set_log_pane()`.
        self.log_pane = log_pane
        self.log_store = log_store if log_store else LogStore(
            prefs=application.prefs)
        self.log_store.set_prefs(application.prefs)
        self.log_store.register_viewer(self)

        self.marked_logs_start: Optional[int] = None
        self.marked_logs_end: Optional[int] = None

        # Search variables
        self.search_text: Optional[str] = None
        self.search_filter: Optional[LogFilter] = None
        self.search_highlight: bool = False
        self.search_matcher = DEFAULT_SEARCH_MATCHER
        self.search_validator = RegexValidator()

        # Container for each log_index matched by active searches.
        self.search_matched_lines: Dict[int, int] = {}
        # Background task to find historical matched lines.
        self.search_match_count_task: Optional[asyncio.Task] = None

        # Flag for automatically jumping to each new search match as they
        # appear.
        self.follow_search_match: bool = False
        self.last_search_matched_log: Optional[int] = None

        # Follow event flag. This is set to by the new_logs_arrived() function
        # as a signal that the log screen should be scrolled to the bottom.
        # This is read by render_content() whenever the screen is drawn.
        self.follow_event: Optional[FollowEvent] = None

        self.log_screen = LogScreen(
            get_log_source=self._get_log_lines,
            get_line_wrapping=self.wrap_lines_enabled,
            get_log_formatter=self._get_table_formatter,
            get_search_filter=lambda: self.search_filter,
            get_search_highlight=lambda: self.search_highlight,
        )

        # Filter
        self.filtering_on: bool = False
        self.filters: 'collections.OrderedDict[str, LogFilter]' = (
            collections.OrderedDict())
        self.filtered_logs: collections.deque = collections.deque()
        self.filter_existing_logs_task: Optional[asyncio.Task] = None

        # Current log line index state variables:
        self._last_log_index = -1
        self._log_index = 0
        self._filtered_log_index = 0
        self._last_start_index = 0
        self._last_end_index = 0
        self._current_start_index = 0
        self._current_end_index = 0
        self._scrollback_start_index = 0

        # LogPane prompt_toolkit container render size.
        self._window_height = 20
        self._window_width = 80
        self._reset_log_screen_on_next_render: bool = True
        self._user_scroll_event: bool = False

        # Max frequency in seconds of prompt_toolkit UI redraws triggered by new
        # log lines.
        self._ui_update_frequency = 0.05
        self._last_ui_update_time = time.time()
        self._last_log_store_index = 0
        self._new_logs_since_last_render = True

        # Should new log lines be tailed?
        self.follow: bool = True

        self.visual_select_mode: bool = False

        # Cache of formatted text tuples used in the last UI render.
        self._line_fragment_cache: List[StyleAndTextTuples] = []

    def view_mode_changed(self) -> None:
        self._reset_log_screen_on_next_render = True

    @property
    def log_index(self):
        if self.filtering_on:
            return self._filtered_log_index
        return self._log_index

    @log_index.setter
    def log_index(self, new_log_index):
        # Save the old log_index
        self._last_log_index = self.log_index
        if self.filtering_on:
            self._filtered_log_index = new_log_index
        else:
            self._log_index = new_log_index

    def _reset_log_index_changed(self) -> None:
        self._last_log_index = self.log_index

    def log_index_changed_since_last_render(self) -> bool:
        return self._last_log_index != self.log_index

    def _set_match_position(self, position: int):
        self.follow = False
        self.log_index = position
        self.save_search_matched_line(position)
        self.log_screen.reset_logs(log_index=self.log_index)
        self.log_screen.shift_selected_log_to_center()
        self._user_scroll_event = True
        self.log_pane.application.redraw_ui()

    def select_next_search_matcher(self):
        matchers = list(SearchMatcher)
        index = matchers.index(self.search_matcher)
        new_index = (index + 1) % len(matchers)
        self.search_matcher = matchers[new_index]

    def search_forwards(self):
        if not self.search_filter:
            return
        self.search_highlight = True

        log_beginning_index = self.hidden_line_count()

        starting_index = self.log_index + 1
        if starting_index > self.get_last_log_index():
            starting_index = log_beginning_index

        _, logs = self._get_log_lines()

        # From current position +1 and down
        for i in range(starting_index, self.get_last_log_index() + 1):
            if self.search_filter.matches(logs[i]):
                self._set_match_position(i)
                return

        # From the beginning to the original start
        for i in range(log_beginning_index, starting_index):
            if self.search_filter.matches(logs[i]):
                self._set_match_position(i)
                return

    def search_backwards(self):
        if not self.search_filter:
            return
        self.search_highlight = True

        log_beginning_index = self.hidden_line_count()

        starting_index = self.log_index - 1
        if starting_index < 0:
            starting_index = self.get_last_log_index()

        _, logs = self._get_log_lines()

        # From current position - 1 and up
        for i in range(starting_index, log_beginning_index - 1, -1):
            if self.search_filter.matches(logs[i]):
                self._set_match_position(i)
                return

        # From the end to the original start
        for i in range(self.get_last_log_index(), starting_index, -1):
            if self.search_filter.matches(logs[i]):
                self._set_match_position(i)
                return

    def set_search_regex(self,
                         text,
                         invert,
                         field,
                         matcher: Optional[SearchMatcher] = None) -> bool:
        search_matcher = matcher if matcher else self.search_matcher
        _LOG.debug(search_matcher)

        regex_text, regex_flags = preprocess_search_regex(
            text, matcher=search_matcher)

        try:
            compiled_regex = re.compile(regex_text, regex_flags)
            self.search_filter = LogFilter(
                regex=compiled_regex,
                input_text=text,
                invert=invert,
                field=field,
            )
            _LOG.debug(self.search_filter)
        except re.error as error:
            _LOG.debug(error)
            return False

        self.search_highlight = True
        self.search_text = regex_text
        return True

    def new_search(
        self,
        text,
        invert=False,
        field: Optional[str] = None,
        search_matcher: Optional[str] = None,
        interactive: bool = True,
    ) -> bool:
        """Start a new search for the given text."""
        valid_matchers = list(s.name for s in SearchMatcher)
        selected_matcher: Optional[SearchMatcher] = None
        if (search_matcher is not None
                and search_matcher.upper() in valid_matchers):
            selected_matcher = SearchMatcher(search_matcher.upper())

        if not self.set_search_regex(text, invert, field, selected_matcher):
            return False

        # Clear matched lines
        self.search_matched_lines = {}

        if interactive:
            # Start count historical search matches task.
            self.search_match_count_task = asyncio.create_task(
                self.count_search_matches())

        # Default search direction when hitting enter in the search bar.
        if interactive:
            self.search_forwards()
        return True

    def save_search_matched_line(self, log_index: int) -> None:
        """Save the log_index at position as a matched line."""
        self.search_matched_lines[log_index] = 0
        # Keep matched lines sorted by position
        self.search_matched_lines = {
            # Save this log_index and its match number.
            log_index: match_number
            for match_number, log_index in enumerate(
                sorted(self.search_matched_lines.keys()))
        }

    def disable_search_highlighting(self):
        self.log_pane.log_view.search_highlight = False

    def _restart_filtering(self):
        # Turn on follow
        if not self.follow:
            self.toggle_follow()

        # Reset filtered logs.
        self.filtered_logs.clear()
        # Reset scrollback start
        self._scrollback_start_index = 0

        # Start filtering existing log lines.
        self.filter_existing_logs_task = asyncio.create_task(
            self.filter_past_logs())

        # Reset existing search
        self.clear_search()

        # Trigger a main menu update to set log window menu titles.
        self.log_pane.application.update_menu_items()
        # Redraw the UI
        self.log_pane.application.redraw_ui()

    def install_new_filter(self):
        """Set a filter using the current search_regex."""
        if not self.search_filter:
            return

        self.filtering_on = True
        self.filters[self.search_text] = copy.deepcopy(self.search_filter)

        self.clear_search()

    def apply_filter(self):
        """Set new filter and schedule historical log filter asyncio task."""
        self.install_new_filter()
        self._restart_filtering()

    def clear_search_highlighting(self):
        self.search_highlight = False
        self._reset_log_screen_on_next_render = True

    def clear_search(self):
        self.search_matched_lines = {}
        self.search_text = None
        self.search_filter = None
        self.search_highlight = False
        self._reset_log_screen_on_next_render = True

    def _get_log_lines(self) -> Tuple[int, collections.deque[LogLine]]:
        logs = self.log_store.logs
        if self.filtering_on:
            logs = self.filtered_logs
        return self._scrollback_start_index, logs

    def _get_visible_log_lines(self):
        _, logs = self._get_log_lines()
        if self._scrollback_start_index > 0:
            return collections.deque(
                itertools.islice(logs, self.hidden_line_count(), len(logs)))
        return logs

    def _get_table_formatter(self) -> Optional[Callable]:
        table_formatter = None
        if self.log_pane.table_view:
            table_formatter = self.log_store.table.formatted_row
        return table_formatter

    def delete_filter(self, filter_text):
        if filter_text not in self.filters:
            return

        # Delete this filter
        del self.filters[filter_text]

        # If no filters left, stop filtering.
        if len(self.filters) == 0:
            self.clear_filters()
        else:
            # Erase existing filtered lines.
            self._restart_filtering()

    def clear_filters(self):
        if not self.filtering_on:
            return
        self.clear_search()
        self.filtering_on = False
        self.filters: 'collections.OrderedDict[str, re.Pattern]' = (
            collections.OrderedDict())
        self.filtered_logs.clear()
        # Reset scrollback start
        self._scrollback_start_index = 0
        if not self.follow:
            self.toggle_follow()

    async def count_search_matches(self):
        """Count search matches and save their locations."""
        # Wait for any filter_existing_logs_task to finish.
        if self.filtering_on and self.filter_existing_logs_task:
            await self.filter_existing_logs_task

        starting_index = self.get_last_log_index()
        ending_index, logs = self._get_log_lines()

        # From the end of the log store to the beginning.
        for i in range(starting_index, ending_index - 1, -1):
            # Is this log a match?
            if self.search_filter.matches(logs[i]):
                self.save_search_matched_line(i)
            # Pause every 100 lines or so
            if i % 100 == 0:
                await asyncio.sleep(.1)

    async def filter_past_logs(self):
        """Filter past log lines."""
        starting_index = self.log_store.get_last_log_index()
        ending_index = -1

        # From the end of the log store to the beginning.
        for i in range(starting_index, ending_index, -1):
            # Is this log a match?
            if self.filter_scan(self.log_store.logs[i]):
                # Add to the beginning of the deque.
                self.filtered_logs.appendleft(self.log_store.logs[i])
            # TODO(tonymd): Tune these values.
            # Pause every 100 lines or so
            if i % 100 == 0:
                await asyncio.sleep(.1)

    def set_log_pane(self, log_pane: 'LogPane'):
        """Set the parent LogPane instance."""
        self.log_pane = log_pane

    def _update_log_index(self) -> ScreenLine:
        line_at_cursor = self.log_screen.get_line_at_cursor_position()
        if line_at_cursor.log_index is not None:
            self.log_index = line_at_cursor.log_index
        return line_at_cursor

    def get_current_line(self) -> int:
        """Return the currently selected log event index."""
        return self.log_index

    def get_total_count(self):
        """Total size of the logs store."""
        return (len(self.filtered_logs)
                if self.filtering_on else self.log_store.get_total_count())

    def get_last_log_index(self):
        total = self.get_total_count()
        return 0 if total < 0 else total - 1

    def clear_scrollback(self):
        """Hide log lines before the max length of the stored logs."""
        # Enable follow and scroll to the bottom, then clear.
        if not self.follow:
            self.toggle_follow()
        self._scrollback_start_index = self.log_index
        self._reset_log_screen_on_next_render = True

    def hidden_line_count(self):
        """Return the number of hidden lines."""
        if self._scrollback_start_index > 0:
            return self._scrollback_start_index + 1
        return 0

    def undo_clear_scrollback(self):
        """Reset the current scrollback start index."""
        self._scrollback_start_index = 0

    def wrap_lines_enabled(self):
        """Get the parent log pane wrap lines setting."""
        if not self.log_pane:
            return False
        return self.log_pane.wrap_lines

    def toggle_follow(self):
        """Toggle auto line following."""
        self.follow = not self.follow
        if self.follow:
            # Disable search match follow mode.
            self.follow_search_match = False
            self.scroll_to_bottom()

    def filter_scan(self, log: 'LogLine'):
        filter_match_count = 0
        for _filter_text, log_filter in self.filters.items():
            if log_filter.matches(log):
                filter_match_count += 1
            else:
                break

        if filter_match_count == len(self.filters):
            return True
        return False

    def new_logs_arrived(self):
        """Check newly arrived log messages.

        Depending on where log statements occur ``new_logs_arrived`` may be in a
        separate thread since it is triggerd by the Python log handler
        ``emit()`` function. In this case the log handler is the LogStore
        instance ``self.log_store``. This function should not redraw the screen
        or scroll.
        """
        latest_total = self.log_store.get_total_count()

        if self.filtering_on:
            # Scan newly arived log lines
            for i in range(self._last_log_store_index, latest_total):
                if self.filter_scan(self.log_store.logs[i]):
                    self.filtered_logs.append(self.log_store.logs[i])

        if self.search_filter:
            last_matched_log: Optional[int] = None
            # Scan newly arived log lines
            for i in range(self._last_log_store_index, latest_total):
                if self.search_filter.matches(self.log_store.logs[i]):
                    self.save_search_matched_line(i)
                    last_matched_log = i
            if last_matched_log and self.follow_search_match:
                # Set the follow event flag for the next render_content call.
                self.follow_event = FollowEvent.SEARCH_MATCH
                self.last_search_matched_log = last_matched_log

        self._last_log_store_index = latest_total
        self._new_logs_since_last_render = True

        if self.follow:
            # Set the follow event flag for the next render_content call.
            self.follow_event = FollowEvent.STICKY_FOLLOW

        # Trigger a UI update
        self._update_prompt_toolkit_ui()

    def _update_prompt_toolkit_ui(self):
        """Update Prompt Toolkit UI if a certain amount of time has passed."""
        emit_time = time.time()
        # Has enough time passed since last UI redraw?
        if emit_time > self._last_ui_update_time + self._ui_update_frequency:
            # Update last log time
            self._last_ui_update_time = emit_time

            # Trigger Prompt Toolkit UI redraw.
            self.log_pane.application.redraw_ui()

    def get_cursor_position(self) -> Point:
        """Return the position of the cursor."""
        return Point(0, self.log_screen.cursor_position)

    def scroll_to_top(self):
        """Move selected index to the beginning."""
        # Stop following so cursor doesn't jump back down to the bottom.
        self.follow = False
        # First possible log index that should be displayed
        log_beginning_index = self.hidden_line_count()
        self.log_index = log_beginning_index
        self.log_screen.reset_logs(log_index=self.log_index)
        self.log_screen.shift_selected_log_to_top()
        self._user_scroll_event = True

    def move_selected_line_to_top(self):
        self.follow = False

        # Update selected line
        self._update_log_index()

        self.log_screen.reset_logs(log_index=self.log_index)
        self.log_screen.shift_selected_log_to_top()
        self._user_scroll_event = True

    def center_log_line(self):
        self.follow = False

        # Update selected line
        self._update_log_index()

        self.log_screen.reset_logs(log_index=self.log_index)
        self.log_screen.shift_selected_log_to_center()
        self._user_scroll_event = True

    def scroll_to_bottom(self, with_sticky_follow: bool = True):
        """Move selected index to the end."""
        # Don't change following state like scroll_to_top.
        self.log_index = max(0, self.get_last_log_index())
        self.log_screen.reset_logs(log_index=self.log_index)

        # Sticky follow mode
        if with_sticky_follow:
            self.follow = True
        self._user_scroll_event = True

    def scroll(self, lines) -> None:
        """Scroll up or down by plus or minus lines.

        This method is only called by user keybindings.
        """
        # If the user starts scrolling, stop auto following.
        self.follow = False

        self.log_screen.scroll_subline(lines)
        self._user_scroll_event = True

        # Update the current log
        current_line = self._update_log_index()

        # Don't check for sticky follow mode if selecting lines.
        if self.visual_select_mode:
            return
        # Is the last log line selected?
        if self.log_index == self.get_last_log_index():
            # Is the last line of the current log selected?
            if current_line.subline + 1 == current_line.height:
                # Sticky follow mode
                self.follow = True

    def visual_selected_log_count(self) -> int:
        if self.marked_logs_start is None or self.marked_logs_end is None:
            return 0
        return (self.marked_logs_end - self.marked_logs_start) + 1

    def clear_visual_selection(self) -> None:
        self.marked_logs_start = None
        self.marked_logs_end = None
        self.visual_select_mode = False
        self._user_scroll_event = True
        self.log_pane.application.redraw_ui()

    def visual_select_all(self) -> None:
        self.marked_logs_start = self._scrollback_start_index
        self.marked_logs_end = self.get_total_count() - 1

        self.visual_select_mode = True
        self._user_scroll_event = True
        self.log_pane.application.redraw_ui()

    def visual_select_up(self) -> None:
        # Select the current line
        self.visual_select_line(self.get_cursor_position(), autoscroll=False)
        # Move the cursor by 1
        self.scroll_up(1)
        # Select the new line
        self.visual_select_line(self.get_cursor_position(), autoscroll=False)

    def visual_select_down(self) -> None:
        # Select the current line
        self.visual_select_line(self.get_cursor_position(), autoscroll=False)
        # Move the cursor by 1
        self.scroll_down(1)
        # Select the new line
        self.visual_select_line(self.get_cursor_position(), autoscroll=False)

    def visual_select_line(self,
                           mouse_position: Point,
                           autoscroll: bool = True) -> None:
        """Mark the log under mouse_position as visually selected."""
        # Check mouse_position is valid
        if not 0 <= mouse_position.y < len(self.log_screen.line_buffer):
            return
        # Update mode flags
        self.visual_select_mode = True
        self.follow = False
        # Get the ScreenLine for the cursor position
        screen_line = self.log_screen.line_buffer[mouse_position.y]
        if screen_line.log_index is None:
            return

        if self.marked_logs_start is None:
            self.marked_logs_start = screen_line.log_index
        if self.marked_logs_end is None:
            self.marked_logs_end = screen_line.log_index

        if screen_line.log_index < self.marked_logs_start:
            self.marked_logs_start = screen_line.log_index
        elif screen_line.log_index > self.marked_logs_end:
            self.marked_logs_end = screen_line.log_index

        # Update cursor position
        self.log_screen.move_cursor_to_position(mouse_position.y)

        # Autoscroll when mouse dragging on the top or bottom of the window.
        if autoscroll:
            if mouse_position.y == 0:
                self.scroll_up(1)
            elif mouse_position.y == self._window_height - 1:
                self.scroll_down(1)

        # Trigger a rerender.
        self._user_scroll_event = True
        self.log_pane.application.redraw_ui()

    def scroll_to_position(self, mouse_position: Point):
        """Set the selected log line to the mouse_position."""
        # Disable follow mode when the user clicks or mouse drags on a log line.
        self.follow = False

        self.log_screen.move_cursor_to_position(mouse_position.y)
        self._update_log_index()

        self._user_scroll_event = True

    def scroll_up_one_page(self):
        """Move the selected log index up by one window height."""
        lines = 1
        if self._window_height > 0:
            lines = self._window_height
        self.scroll(-1 * lines)

    def scroll_down_one_page(self):
        """Move the selected log index down by one window height."""
        lines = 1
        if self._window_height > 0:
            lines = self._window_height
        self.scroll(lines)

    def scroll_down(self, lines=1):
        """Move the selected log index down by one or more lines."""
        self.scroll(lines)

    def scroll_up(self, lines=1):
        """Move the selected log index up by one or more lines."""
        self.scroll(-1 * lines)

    def log_start_end_indexes_changed(self) -> bool:
        return (self._last_start_index != self._current_start_index
                or self._last_end_index != self._current_end_index)

    def render_table_header(self):
        """Get pre-formatted table header."""
        return self.log_store.render_table_header()

    def render_content(self) -> list:
        """Return logs to display on screen as a list of FormattedText tuples.

        This function determines when the log screen requires re-rendeing based
        on user scroll events, follow mode being on, or log pane being
        empty. The FormattedText tuples passed to prompt_toolkit are cached if
        no updates are required.
        """
        screen_update_needed = False

        # Check window size
        if self.log_pane.pane_resized():
            self._window_width = self.log_pane.current_log_pane_width
            self._window_height = self.log_pane.current_log_pane_height
            self.log_screen.resize(self._window_width, self._window_height)
            self._reset_log_screen_on_next_render = True

        if self.follow_event is not None:
            if (self.follow_event == FollowEvent.SEARCH_MATCH
                    and self.last_search_matched_log):
                self.log_index = self.last_search_matched_log
                self.last_search_matched_log = None
                self._reset_log_screen_on_next_render = True

            elif self.follow_event == FollowEvent.STICKY_FOLLOW:
                # Jump to the last log message
                self.log_index = max(0, self.get_last_log_index())

            self.follow_event = None
            screen_update_needed = True

        if self._reset_log_screen_on_next_render or self.log_screen.empty():
            # Clear the reset flag.
            self._reset_log_screen_on_next_render = False
            self.log_screen.reset_logs(log_index=self.log_index)
            screen_update_needed = True

        elif self.follow and self._new_logs_since_last_render:
            # Follow mode is on so add new logs to the screen
            self._new_logs_since_last_render = False

            current_log_index = self.log_index
            last_rendered_log_index = self.log_screen.last_appended_log_index
            # If so many logs have arrived than can fit on the screen, redraw
            # the whole screen from the new position.
            if (current_log_index -
                    last_rendered_log_index) > self.log_screen.height:
                self.log_screen.reset_logs(log_index=self.log_index)
            # A small amount of logs have arrived, append them one at a time
            # without redrawing the whole screen.
            else:
                for i in range(last_rendered_log_index + 1,
                               current_log_index + 1):
                    self.log_screen.append_log(i)

            screen_update_needed = True

        if self.follow:
            # Select the last line for follow mode.
            self.log_screen.move_cursor_to_bottom()
            screen_update_needed = True

        if self._user_scroll_event:
            self._user_scroll_event = False
            screen_update_needed = True

        if screen_update_needed:
            self._line_fragment_cache = self.log_screen.get_lines(
                marked_logs_start=self.marked_logs_start,
                marked_logs_end=self.marked_logs_end,
            )
        return self._line_fragment_cache

    def _logs_to_text(
        self,
        use_table_formatting: bool = True,
        selected_lines_only: bool = False,
    ) -> str:
        """Convert all or selected log messages to plaintext."""
        def get_table_string(log: LogLine) -> str:
            return remove_formatting(self.log_store.table.formatted_row(log))

        formatter: Callable[[LogLine],
                            str] = operator.attrgetter('ansi_stripped_log')
        if use_table_formatting:
            formatter = get_table_string

        _start_log_index, log_source = self._get_log_lines()

        log_index_range = range(self._scrollback_start_index,
                                self.get_total_count())
        if (selected_lines_only and self.marked_logs_start is not None
                and self.marked_logs_end is not None):
            log_index_range = range(self.marked_logs_start,
                                    self.marked_logs_end + 1)

        text_output = ''
        for i in log_index_range:
            log_text = formatter(log_source[i])
            text_output += log_text
            if not log_text.endswith('\n'):
                text_output += '\n'

        return text_output

    def export_logs(
        self,
        use_table_formatting: bool = True,
        selected_lines_only: bool = False,
        file_name: Optional[str] = None,
        to_clipboard: bool = False,
        add_markdown_fence: bool = False,
    ) -> bool:
        """Export log lines to file or clipboard."""
        text_output = self._logs_to_text(use_table_formatting,
                                         selected_lines_only)

        if file_name:
            target_path = Path(file_name).expanduser()
            with target_path.open('w') as output_file:
                output_file.write(text_output)
            _LOG.debug('Saved to file: %s', file_name)

        elif to_clipboard:
            if add_markdown_fence:
                text_output = '```\n' + text_output + '```\n'
            self.log_pane.application.application.clipboard.set_text(
                text_output)
            _LOG.debug('Copied logs to clipboard.')

        return True
