# 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
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

        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] = []

        # Check if any logs are already in the log_store and update the view.
        self.new_logs_arrived()

    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 if the log window is visible.
        if self.log_pane.show_pane:
            self.log_pane.application.logs_redraw()

    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
