# Copyright 2022 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.
"""LogScreen tracks lines to display on screen with a set of ScreenLines."""

from __future__ import annotations
import collections
import dataclasses
import logging
from typing import Callable, List, Optional, Tuple, TYPE_CHECKING

from prompt_toolkit.formatted_text import (
    to_formatted_text,
    StyleAndTextTuples,
)

from pw_console.log_filter import LogFilter
from pw_console.text_formatting import (
    fill_character_width,
    insert_linebreaks,
    split_lines,
)

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

_LOG = logging.getLogger(__package__)


@dataclasses.dataclass
class ScreenLine:
    """A single line of text for displaying on screen.

    Instances of ScreenLine are stored in a LogScreen's line_buffer deque. When
    a new log message is added it may be converted into multiple ScreenLine
    instances if the text is wrapped across multiple lines.

    For example: say our screen is 80 characters wide and a log message 240
    characters long needs to be displayed. With line wrapping on we will need
    240/80 = 3 lines to show the full message. Say also that this single log
    message is at index #5 in the LogStore classes deque, this is the log_index
    value. This single log message will then be split into 3 separate
    ScreenLine instances:

    ::
        ScreenLine(fragments=[('', 'Log message text line one')],
                   log_index=5, subline=0, height=3)
        ScreenLine(fragments=[('', 'Log message text line two')],
                   log_index=5, subline=1, height=3)
        ScreenLine(fragments=[('', 'Log message text line three')],
                   log_index=5, subline=2, height=3)

    Each `fragments` attribute will store the formatted text indended to be
    direcly drawn to the screen. Since these three lines are all displaying the
    same log message their `log_index` reference will be the same. The `subline`
    attribute is the zero-indexed number for this log's wrapped line count and
    `height` is the total ScreenLines needed to show this log message.

    Continuing with this example say the next two log messages to display both
    fit on screen with no wrapping. They will both be represented with one
    ScreenLine each:

    ::
        ScreenLine(fragments=[('', 'Another log message')],
                   log_index=6, subline=0, height=1)
        ScreenLine(fragments=[('', 'Yet another log message')],
                   log_index=7, subline=0, height=1)

    The `log_index` is different for each since these are both separate
    logs. The subline is 0 since each line is the first one for this log. Both
    have a height of 1 since no line wrapping was performed.
    """
    # The StyleAndTextTuples for this line ending with a '\n'. These are the raw
    # prompt_toolkit formatted text tuples to display on screen. The colors and
    # spacing can change depending on the formatters used in the
    # LogScreen._get_fragments_per_line() function.
    fragments: StyleAndTextTuples

    # Log index reference for this screen line. This is the index to where the
    # log message resides in the parent LogStore.logs deque. It is set to None
    # if this is an empty ScreenLine. If a log message requires line wrapping
    # then each resulting ScreenLine instance will have the same log_index
    # value.
    #
    # This log_index may also be the integer index into a LogView.filtered_logs
    # deque depending on if log messages are being filtered by the user. The
    # LogScreen class below doesn't need to do anything different in either
    # case. It's the responsibility of LogScreen.get_log_source() to return the
    # correct source.
    #
    # Note this is NOT an index into LogScreen.line_buffer.
    log_index: Optional[int] = None

    # Keep track the total height and subline number for this log message.
    # For example this line could be subline (0, 1, or 2) of a log message with
    # a total height 3.

    # Subline index.
    subline: int = 0
    # Total height in lines of text (also ScreenLine count) that the log message
    # referred to by log_index requires. When a log message is split across
    # multiple lines height will be set to the same value for each ScreenLine
    # instance.
    height: int = 1

    # Empty lines will have no log_index
    def empty(self) -> bool:
        return self.log_index is None


@dataclasses.dataclass
class LogScreen:
    """LogScreen maintains the state of visible logs on screen.

    It is responsible for moving the cursor_position, prepending and appending
    log lines as the user moves the cursor."""
    # Callable functions to retrieve logs and display formatting.
    get_log_source: Callable[[], Tuple[int, collections.deque[LogLine]]]
    get_line_wrapping: Callable[[], bool]
    get_log_formatter: Callable[[], Optional[Callable[[LogLine],
                                                      StyleAndTextTuples]]]
    get_search_filter: Callable[[], Optional[LogFilter]]
    get_search_highlight: Callable[[], bool]

    # Window row of the current cursor position
    cursor_position: int = 0
    # Screen width and height in number of characters.
    width: int = 0
    height: int = 0
    # Buffer of literal text lines to be displayed on screen. Each visual line
    # is represented by a ScreenLine instance and will have a max width equal
    # to the screen's width. If any given whole log message requires line
    # wrapping to be displayed it will be represented by multiple ScreenLine
    # instances in this deque.
    line_buffer: collections.deque[ScreenLine] = dataclasses.field(
        default_factory=collections.deque)

    def __post_init__(self) -> None:
        # Empty screen flag. Will be true if the screen contains only newlines.
        self._empty: bool = True
        # Save the last log index when appending. Useful for tracking how many
        # new lines need appending in follow mode.
        self.last_appended_log_index: int = 0

    def _fill_top_with_empty_lines(self) -> None:
        """Add empty lines to fill the remaining empty screen space."""
        for _ in range(self.height - len(self.line_buffer)):
            self.line_buffer.appendleft(ScreenLine([('', '')]))

    def clear_screen(self) -> None:
        """Erase all lines and fill with empty lines."""
        self.line_buffer.clear()
        self._fill_top_with_empty_lines()
        self._empty = True

    def empty(self) -> bool:
        """Return True if the screen has no lines with content."""
        return self._empty

    def reset_logs(
        self,
        log_index: int = 0,
    ) -> None:
        """Erase the screen and append logs starting from log_index."""
        self.clear_screen()

        start_log_index, log_source = self.get_log_source()
        if len(log_source) == 0:
            return

        # Append at most at most the window height number worth of logs. If the
        # number of available logs is less, use that amount.
        max_log_messages_to_fetch = min(self.height, len(log_source))

        # Including the target log_index, fetch the desired logs.
        # For example if we are rendering log_index 10 and the window height is
        # 6 the range below will be:
        # >>> list(i for i in range((10 - 6) + 1, 10 + 1))
        # [5, 6, 7, 8, 9, 10]
        for i in range((log_index - max_log_messages_to_fetch) + 1,
                       log_index + 1):
            # If i is < 0 it's an invalid log, skip to the next line. The next
            # index could be 0 or higher since we are traversing in increasing
            # order.
            if i < start_log_index:
                continue
            self.append_log(i)
        # Make sure the bottom line is highlighted.
        self.move_cursor_to_bottom()

    def resize(self, width, height) -> None:
        """Update screen width and height.

        Following a resize the caller should run reset_logs()."""
        self.width = width
        self.height = height

    def get_lines(
        self,
        marked_logs_start: Optional[int] = None,
        marked_logs_end: Optional[int] = None,
    ) -> List[StyleAndTextTuples]:
        """Return lines for final display.

        Styling is added for the line under the cursor."""
        if not marked_logs_start:
            marked_logs_start = -1
        if not marked_logs_end:
            marked_logs_end = -1

        all_lines: List[StyleAndTextTuples] = []
        # Loop through a copy of the line_buffer in case it is mutated before
        # this function is complete.
        for i, line in enumerate(list(self.line_buffer)):

            # Is this line the cursor_position? Apply line highlighting
            if (i == self.cursor_position
                    and (self.cursor_position < len(self.line_buffer))
                    and not self.line_buffer[self.cursor_position].empty()):
                # Fill in empty charaters to the width of the screen. This
                # ensures the backgound is highlighted to the edge of the
                # screen.
                new_fragments = fill_character_width(
                    line.fragments,
                    len(line.fragments) - 1,  # -1 for the ending line break
                    self.width,
                )

                # Apply a style to highlight this line.
                all_lines.append(
                    to_formatted_text(new_fragments,
                                      style='class:selected-log-line'))
            elif line.log_index is not None and (
                    marked_logs_start <= line.log_index <= marked_logs_end):
                new_fragments = fill_character_width(
                    line.fragments,
                    len(line.fragments) - 1,  # -1 for the ending line break
                    self.width,
                )

                # Apply a style to highlight this line.
                all_lines.append(
                    to_formatted_text(new_fragments,
                                      style='class:marked-log-line'))

            else:
                all_lines.append(line.fragments)

        return all_lines

    def _prepend_line(self, line: ScreenLine) -> None:
        """Add a line to the top of the screen."""
        self.line_buffer.appendleft(line)
        self._empty = False

    def _append_line(self, line: ScreenLine) -> None:
        """Add a line to the bottom of the screen."""
        self.line_buffer.append(line)
        self._empty = False

    def _trim_top_lines(self) -> None:
        """Remove lines from the top if larger than the screen height."""
        overflow_amount = len(self.line_buffer) - self.height
        for _ in range(overflow_amount):
            self.line_buffer.popleft()

    def _trim_bottom_lines(self) -> None:
        """Remove lines from the bottom if larger than the screen height."""
        overflow_amount = len(self.line_buffer) - self.height
        for _ in range(overflow_amount):
            self.line_buffer.pop()

    def move_cursor_up(self, line_count: int) -> int:
        """Move the cursor up as far as it can go without fetching new lines.

        Args:
            line_count: A negative number of lines to move the cursor by.

        Returns:
            int: The remaining line count that was not moved. This is the number
            of new lines that need to be fetched and prepended to the screen
            line buffer."""
        remaining_lines = line_count

        # Loop from a negative line_count value to zero.
        # For example if line_count is -5 the loop will traverse:
        # >>> list(i for i in range(-5, 0, 1))
        # [-5, -4, -3, -2, -1]
        for _ in range(line_count, 0, 1):
            new_index = self.cursor_position - 1
            if new_index < 0:
                break
            if (new_index < len(self.line_buffer)
                    and self.line_buffer[new_index].empty()):
                # The next line is empty and has no content.
                break
            self.cursor_position -= 1
            remaining_lines += 1
        return remaining_lines

    def move_cursor_down(self, line_count: int) -> int:
        """Move the cursor down as far as it can go without fetching new lines.

        Args:
            line_count: A positive number of lines to move the cursor down by.

        Returns:
            int: The remaining line count that was not moved. This is the number
            of new lines that need to be fetched and appended to the screen line
            buffer."""
        remaining_lines = line_count
        for _ in range(line_count):
            new_index = self.cursor_position + 1
            if new_index >= self.height:
                break
            if (new_index < len(self.line_buffer)
                    and self.line_buffer[new_index].empty()):
                # The next line is empty and has no content.
                break
            self.cursor_position += 1
            remaining_lines -= 1
        return remaining_lines

    def move_cursor_to_bottom(self) -> None:
        """Move the cursor to the bottom of the screen.

        Only use this for movement not initiated by users. For example if new
        logs were just added to the bottom of the screen in follow
        mode. The LogScreen class does not allow scrolling beyond the bottom of
        the content so the cursor will fall on a log message as long as there
        are some log messages. If there are no log messages the line is not
        highlighted by get_lines()."""
        self.cursor_position = self.height - 1

    def move_cursor_to_position(self, window_row: int) -> None:
        """Move the cursor to a line if there is a log message there."""
        if window_row >= len(self.line_buffer):
            return
        if 0 <= window_row < self.height:
            current_line = self.line_buffer[window_row]
            if current_line.log_index is not None:
                self.cursor_position = window_row

    def _move_selection_to_log(self, log_index: int, subline: int) -> None:
        """Move the cursor to the location of log_index."""
        for i, line in enumerate(self.line_buffer):
            if line.log_index == log_index and line.subline == subline:
                self.cursor_position = i
                return

    def shift_selected_log_to_top(self) -> None:
        """Shift the selected line to the top.

        This moves the lines on screen and keeps the originally selected line
        highlighted. Example use case: when jumping to a search match the
        matched line will be shown at the top of the screen."""
        if not 0 <= self.cursor_position < len(self.line_buffer):
            return

        current_line = self.line_buffer[self.cursor_position]
        amount = max(self.cursor_position, current_line.height)
        amount -= current_line.subline
        remaining_lines = self.scroll_subline(amount)
        if remaining_lines != 0 and current_line.log_index is not None:
            # Restore original selected line.
            self._move_selection_to_log(current_line.log_index,
                                        current_line.subline)
            return
        # Lines scrolled as expected, set cursor_position to top.
        self.cursor_position = 0

    def shift_selected_log_to_center(self) -> None:
        """Shift the selected line to the center.

        This moves the lines on screen and keeps the originally selected line
        highlighted. Example use case: when jumping to a search match the
        matched line will be shown at the center of the screen."""
        if not 0 <= self.cursor_position < len(self.line_buffer):
            return

        half_height = int(self.height / 2)
        current_line = self.line_buffer[self.cursor_position]

        amount = max(self.cursor_position - half_height, current_line.height)
        amount -= current_line.subline

        remaining_lines = self.scroll_subline(amount)
        if remaining_lines != 0 and current_line.log_index is not None:
            # Restore original selected line.
            self._move_selection_to_log(current_line.log_index,
                                        current_line.subline)
            return

        # Lines scrolled as expected, set cursor_position to center.
        self.cursor_position -= amount
        self.cursor_position -= (current_line.height - 1)

    def scroll_subline(self, line_count: int = 1) -> int:
        """Move the cursor down or up by positive or negative lines.

        Args:
            line_count: A positive or negative number of lines the cursor should
                move. Positive for down, negative for up.

        Returns:
            int: The remaining line count that was not moved. This is the number
            of new lines that could not be fetched in the case that the top or
            bottom of available log message lines was reached."""
        # Move self.cursor_position as far as it can go on screen without
        # fetching new log message lines.
        if line_count > 0:
            remaining_lines = self.move_cursor_down(line_count)
        else:
            remaining_lines = self.move_cursor_up(line_count)

        if remaining_lines == 0:
            # No more lines needed, return
            return remaining_lines

        # Top or bottom of the screen was reached, fetch and add new log lines.
        if remaining_lines < 0:
            return self.fetch_subline_up(remaining_lines)
        return self.fetch_subline_down(remaining_lines)

    def fetch_subline_up(self, line_count: int = -1) -> int:
        """Fetch new lines from the top in order of decreasing log_indexes.

        Args:
            line_count: A negative number of lines that should be fetched and
                added to the top of the screen.

        Returns:
            int: The number of lines that were not fetched. Returns 0 if the
                desired number of lines were fetched successfully."""
        start_log_index, _log_source = self.get_log_source()
        remaining_lines = line_count
        for _ in range(line_count, 0, 1):
            current_line = self.get_line_at_cursor_position()
            if current_line.log_index is None:
                return remaining_lines + 1

            target_log_index: int
            target_subline: int

            # If the current subline is at the start of this log, fetch the
            # previous log message's last subline.
            if current_line.subline == 0:
                target_log_index = current_line.log_index - 1
                # Set -1 to signal fetching the previous log's last subline
                target_subline = -1
            else:
                # Get previous sub line of current log
                target_log_index = current_line.log_index
                target_subline = current_line.subline - 1

            if target_log_index < start_log_index:
                # Invalid log_index, don't scroll further
                return remaining_lines + 1

            self.prepend_log(target_log_index, subline=target_subline)
            remaining_lines += 1

        return remaining_lines

    def get_line_at_cursor_position(self) -> ScreenLine:
        """Returns the ScreenLine under the cursor."""
        if (self.cursor_position >= len(self.line_buffer)
                or self.cursor_position < 0):
            return ScreenLine([('', '')])
        return self.line_buffer[self.cursor_position]

    def fetch_subline_down(self, line_count: int = 1) -> int:
        """Fetch new lines from the bottom in order of increasing log_indexes.

        Args:
            line_count: A positive number of lines that should be fetched and
                added to the bottom of the screen.

        Returns:
            int: The number of lines that were not fetched. Returns 0 if the
                desired number of lines were fetched successfully."""
        _start_log_index, log_source = self.get_log_source()
        remaining_lines = line_count
        for _ in range(line_count):
            # Skip this line if not at the bottom
            if self.cursor_position < self.height - 1:
                self.cursor_position += 1
                continue

            current_line = self.get_line_at_cursor_position()
            if current_line.log_index is None:
                return remaining_lines - 1

            target_log_index: int
            target_subline: int

            # If the current subline is at the height of this log, fetch the
            # next log message.
            if current_line.subline == current_line.height - 1:
                # Get next log's first subline
                target_log_index = current_line.log_index + 1
                target_subline = 0
            else:
                # Get next sub line of current log
                target_log_index = current_line.log_index
                target_subline = current_line.subline + 1

            if target_log_index >= len(log_source):
                # Invalid log_index, don't scroll further
                return remaining_lines - 1

            self.append_log(target_log_index, subline=target_subline)
            remaining_lines -= 1

        return remaining_lines

    def first_rendered_log_index(self) -> Optional[int]:
        """Scan the screen for the first valid log_index and return it."""
        log_index = None
        for i in range(self.height):
            if i >= len(self.line_buffer):
                break
            if self.line_buffer[i].log_index is not None:
                log_index = self.line_buffer[i].log_index
                break
        return log_index

    def last_rendered_log_index(self) -> Optional[int]:
        """Return the last log_index shown on screen."""
        log_index = None
        if len(self.line_buffer) == 0:
            return None
        if self.line_buffer[-1].log_index is not None:
            log_index = self.line_buffer[-1].log_index
        return log_index

    def _get_fragments_per_line(self,
                                log_index: int) -> List[StyleAndTextTuples]:
        """Return a list of lines wrapped to the screen width for a log.

        Before fetching the log message this function updates the log_source and
        formatting options."""
        _start_log_index, log_source = self.get_log_source()
        if log_index >= len(log_source):
            return []
        log = log_source[log_index]
        table_formatter = self.get_log_formatter()
        truncate_lines = not self.get_line_wrapping()
        search_filter = self.get_search_filter()
        search_highlight = self.get_search_highlight()

        # Select the log display formatter; table or standard.
        fragments: StyleAndTextTuples = []
        if table_formatter:
            fragments = table_formatter(log)
        else:
            fragments = log.get_fragments()

        # Apply search term highlighting.
        if search_filter and search_highlight and search_filter.matches(log):
            fragments = search_filter.highlight_search_matches(fragments)

        # Word wrap the log message or truncate to screen width
        line_fragments, _log_line_height = insert_linebreaks(
            fragments,
            max_line_width=self.width,
            truncate_long_lines=truncate_lines)
        # Convert the existing flattened fragments to a list of lines.
        fragments_per_line = split_lines(line_fragments)

        return fragments_per_line

    def prepend_log(
        self,
        log_index: int,
        subline: Optional[int] = None,
    ) -> None:
        """Add a log message or a single line to the top of the screen.

        Args:
            log_index: The index of the log message to fetch.
            subline: The desired subline of the log message. When displayed on
                screen the log message may take up more than one line. If
                subline is 0 or higher that line will be added. If subline is -1
                the last subline will be prepended regardless of the total log
                message height.
        """
        fragments_per_line = self._get_fragments_per_line(log_index)

        # Target the last subline if the subline arg is set to -1.
        fetch_last_subline = (subline == -1)

        for line_index, line in enumerate(fragments_per_line):
            # If we are looking for a specific subline and this isn't it, skip.
            if subline is not None:
                # If subline is set to -1 we need to append the last subline of
                # this log message. Skip this line if it isn't the last one.
                if fetch_last_subline and (line_index !=
                                           len(fragments_per_line) - 1):
                    continue
                # If subline is not -1 (0 or higher) and this isn't the desired
                # line, skip to the next one.
                if not fetch_last_subline and line_index != subline:
                    continue

            self._prepend_line(
                ScreenLine(
                    fragments=line,
                    log_index=log_index,
                    subline=line_index,
                    height=len(fragments_per_line),
                ))

        # Remove lines from the bottom if over the screen height.
        if len(self.line_buffer) > self.height:
            self._trim_bottom_lines()

    def append_log(
        self,
        log_index: int,
        subline: Optional[int] = None,
    ) -> None:
        """Add a log message or a single line to the bottom of the screen."""
        # Save this log_index
        self.last_appended_log_index = log_index
        fragments_per_line = self._get_fragments_per_line(log_index)

        for line_index, line in enumerate(fragments_per_line):
            # If we are looking for a specific subline and this isn't it, skip.
            if subline is not None and line_index != subline:
                continue

            self._append_line(
                ScreenLine(
                    fragments=line,
                    log_index=log_index,
                    subline=line_index,
                    height=len(fragments_per_line),
                ))

        # Remove lines from the top if over the screen height.
        if len(self.line_buffer) > self.height:
            self._trim_top_lines()
