# 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.
"""LogPane class."""

import functools
import logging
import re
from typing import (
    Any,
    Callable,
    List,
    Optional,
    TYPE_CHECKING,
    Tuple,
    Union,
)

from prompt_toolkit.application.current import get_app
from prompt_toolkit.filters import (
    Condition,
    has_focus,
)
from prompt_toolkit.formatted_text import StyleAndTextTuples
from prompt_toolkit.key_binding import (
    KeyBindings,
    KeyPressEvent,
    KeyBindingsBase,
)
from prompt_toolkit.layout import (
    ConditionalContainer,
    Float,
    FloatContainer,
    UIContent,
    UIControl,
    VerticalAlign,
    Window,
)
from prompt_toolkit.mouse_events import MouseEvent, MouseEventType, MouseButton

import pw_console.widgets.checkbox
import pw_console.style
from pw_console.log_view import LogView
from pw_console.log_pane_toolbars import (
    LineInfoBar,
    TableToolbar,
)
from pw_console.log_pane_saveas_dialog import LogPaneSaveAsDialog
from pw_console.log_pane_selection_dialog import LogPaneSelectionDialog
from pw_console.log_store import LogStore
from pw_console.search_toolbar import SearchToolbar
from pw_console.filter_toolbar import FilterToolbar
from pw_console.widgets import (
    ToolbarButton,
    WindowPane,
    WindowPaneHSplit,
    WindowPaneToolbar,
)

if TYPE_CHECKING:
    from pw_console.console_app import ConsoleApp

_LOG_OUTPUT_SCROLL_AMOUNT = 5
_LOG = logging.getLogger(__package__)


class LogContentControl(UIControl):
    """LogPane prompt_toolkit UIControl for displaying LogContainer lines."""
    def __init__(self, log_pane: 'LogPane') -> None:
        # pylint: disable=too-many-locals
        self.log_pane = log_pane
        self.log_view = log_pane.log_view

        # Mouse drag visual selection flags.
        self.visual_select_mode_drag_start = False
        self.visual_select_mode_drag_stop = False

        self.uicontent: Optional[UIContent] = None
        self.lines: List[StyleAndTextTuples] = []

        # Key bindings.
        key_bindings = KeyBindings()
        register = log_pane.application.prefs.register_keybinding

        @register('log-pane.shift-line-to-top', key_bindings)
        def _shift_log_to_top(_event: KeyPressEvent) -> None:
            """Shift the selected log line to the top."""
            self.log_view.move_selected_line_to_top()

        @register('log-pane.shift-line-to-center', key_bindings)
        def _shift_log_to_center(_event: KeyPressEvent) -> None:
            """Shift the selected log line to the center."""
            self.log_view.center_log_line()

        @register('log-pane.toggle-wrap-lines', key_bindings)
        def _toggle_wrap_lines(_event: KeyPressEvent) -> None:
            """Toggle log line wrapping."""
            self.log_pane.toggle_wrap_lines()

        @register('log-pane.toggle-table-view', key_bindings)
        def _toggle_table_view(_event: KeyPressEvent) -> None:
            """Toggle table view."""
            self.log_pane.toggle_table_view()

        @register('log-pane.duplicate-log-pane', key_bindings)
        def _duplicate(_event: KeyPressEvent) -> None:
            """Duplicate this log pane."""
            self.log_pane.duplicate()

        @register('log-pane.remove-duplicated-log-pane', key_bindings)
        def _delete(_event: KeyPressEvent) -> None:
            """Remove log pane."""
            if self.log_pane.is_a_duplicate:
                self.log_pane.application.window_manager.remove_pane(
                    self.log_pane)

        @register('log-pane.clear-history', key_bindings)
        def _clear_history(_event: KeyPressEvent) -> None:
            """Clear log pane history."""
            self.log_pane.clear_history()

        @register('log-pane.scroll-to-top', key_bindings)
        def _scroll_to_top(_event: KeyPressEvent) -> None:
            """Scroll to top."""
            self.log_view.scroll_to_top()

        @register('log-pane.scroll-to-bottom', key_bindings)
        def _scroll_to_bottom(_event: KeyPressEvent) -> None:
            """Scroll to bottom."""
            self.log_view.scroll_to_bottom()

        @register('log-pane.toggle-follow', key_bindings)
        def _toggle_follow(_event: KeyPressEvent) -> None:
            """Toggle log line following."""
            self.log_pane.toggle_follow()

        @register('log-pane.move-cursor-up', key_bindings)
        def _up(_event: KeyPressEvent) -> None:
            """Move cursor up."""
            self.log_view.scroll_up()

        @register('log-pane.move-cursor-down', key_bindings)
        def _down(_event: KeyPressEvent) -> None:
            """Move cursor down."""
            self.log_view.scroll_down()

        @register('log-pane.visual-select-up', key_bindings)
        def _visual_select_up(_event: KeyPressEvent) -> None:
            """Select previous log line."""
            self.log_view.visual_select_up()

        @register('log-pane.visual-select-down', key_bindings)
        def _visual_select_down(_event: KeyPressEvent) -> None:
            """Select next log line."""
            self.log_view.visual_select_down()

        @register('log-pane.scroll-page-up', key_bindings)
        def _pageup(_event: KeyPressEvent) -> None:
            """Scroll the logs up by one page."""
            self.log_view.scroll_up_one_page()

        @register('log-pane.scroll-page-down', key_bindings)
        def _pagedown(_event: KeyPressEvent) -> None:
            """Scroll the logs down by one page."""
            self.log_view.scroll_down_one_page()

        @register('log-pane.save-copy', key_bindings)
        def _start_saveas(_event: KeyPressEvent) -> None:
            """Save logs to a file."""
            self.log_pane.start_saveas()

        @register('log-pane.search', key_bindings)
        def _start_search(_event: KeyPressEvent) -> None:
            """Start searching."""
            self.log_pane.start_search()

        @register('log-pane.search-next-match', key_bindings)
        def _next_search(_event: KeyPressEvent) -> None:
            """Next search match."""
            self.log_view.search_forwards()

        @register('log-pane.search-previous-match', key_bindings)
        def _previous_search(_event: KeyPressEvent) -> None:
            """Previous search match."""
            self.log_view.search_backwards()

        @register('log-pane.visual-select-all', key_bindings)
        def _select_all_logs(_event: KeyPressEvent) -> None:
            """Clear search."""
            self.log_pane.log_view.visual_select_all()

        @register('log-pane.deselect-cancel-search', key_bindings)
        def _clear_search_and_selection(_event: KeyPressEvent) -> None:
            """Clear selection or search."""
            if self.log_pane.log_view.visual_select_mode:
                self.log_pane.log_view.clear_visual_selection()
            elif self.log_pane.search_bar_active:
                self.log_pane.search_toolbar.cancel_search()

        @register('log-pane.search-apply-filter', key_bindings)
        def _apply_filter(_event: KeyPressEvent) -> None:
            """Apply current search as a filter."""
            self.log_pane.search_toolbar.close_search_bar()
            self.log_view.apply_filter()

        @register('log-pane.clear-filters', key_bindings)
        def _clear_filter(_event: KeyPressEvent) -> None:
            """Reset / erase active filters."""
            self.log_view.clear_filters()

        self.key_bindings: KeyBindingsBase = key_bindings

    def is_focusable(self) -> bool:
        return True

    def get_key_bindings(self) -> Optional[KeyBindingsBase]:
        return self.key_bindings

    def preferred_width(self, max_available_width: int) -> int:
        """Return the width of the longest line."""
        line_lengths = [len(l) for l in self.lines]
        return max(line_lengths)

    def preferred_height(
        self,
        width: int,
        max_available_height: int,
        wrap_lines: bool,
        get_line_prefix,
    ) -> Optional[int]:
        """Return the preferred height for the log lines."""
        content = self.create_content(width, None)
        return content.line_count

    def create_content(self, width: int, height: Optional[int]) -> UIContent:
        # Update lines to render
        self.lines = self.log_view.render_content()

        # Create a UIContent instance if none exists
        if self.uicontent is None:
            self.uicontent = UIContent(get_line=lambda i: self.lines[i],
                                       line_count=len(self.lines),
                                       show_cursor=False)

        # Update line_count
        self.uicontent.line_count = len(self.lines)

        return self.uicontent

    def mouse_handler(self, mouse_event: MouseEvent):
        """Mouse handler for this control."""
        mouse_position = mouse_event.position

        # Left mouse button release should:
        # 1. check if a mouse drag just completed.
        # 2. If not in focus, switch focus to this log pane
        #    If in focus, move the cursor to that position.
        if (mouse_event.event_type == MouseEventType.MOUSE_UP
                and mouse_event.button == MouseButton.LEFT):

            # If a drag was in progress and this is the first mouse release
            # press, set the stop flag.
            if (self.visual_select_mode_drag_start
                    and not self.visual_select_mode_drag_stop):
                self.visual_select_mode_drag_stop = True

            if not has_focus(self)():
                # Focus the save as dialog if open.
                if self.log_pane.saveas_dialog_active:
                    get_app().layout.focus(self.log_pane.saveas_dialog)
                # Focus the search bar if open.
                elif self.log_pane.search_bar_active:
                    get_app().layout.focus(self.log_pane.search_toolbar)
                # Otherwise, focus on the log pane content.
                else:
                    get_app().layout.focus(self)
                # Mouse event handled, return None.
                return None

            # Log pane in focus already, move the cursor to the position of the
            # mouse click.
            self.log_pane.log_view.scroll_to_position(mouse_position)
            # Mouse event handled, return None.
            return None

        # Mouse drag with left button should start selecting lines.
        # The log pane does not need to be in focus to start this.
        if (mouse_event.event_type == MouseEventType.MOUSE_MOVE
                and mouse_event.button == MouseButton.LEFT):
            # If a previous mouse drag was completed, clear the selection.
            if (self.visual_select_mode_drag_start
                    and self.visual_select_mode_drag_stop):
                self.log_pane.log_view.clear_visual_selection()
            # Drag select in progress, set flags accordingly.
            self.visual_select_mode_drag_start = True
            self.visual_select_mode_drag_stop = False

            self.log_pane.log_view.visual_select_line(mouse_position)
            # Mouse event handled, return None.
            return None

        # Mouse wheel events should move the cursor +/- some amount of lines
        # even if this pane is not in focus.
        if mouse_event.event_type == MouseEventType.SCROLL_DOWN:
            self.log_pane.log_view.scroll_down(lines=_LOG_OUTPUT_SCROLL_AMOUNT)
            # Mouse event handled, return None.
            return None

        if mouse_event.event_type == MouseEventType.SCROLL_UP:
            self.log_pane.log_view.scroll_up(lines=_LOG_OUTPUT_SCROLL_AMOUNT)
            # Mouse event handled, return None.
            return None

        # Mouse event not handled, return NotImplemented.
        return NotImplemented


class LogPane(WindowPane):
    """LogPane class."""

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

    def __init__(
        self,
        application: Any,
        pane_title: str = 'Logs',
        log_store: Optional[LogStore] = None,
    ):
        super().__init__(application, pane_title)

        # TODO(tonymd): Read these settings from a project (or user) config.
        self.wrap_lines = False
        self._table_view = True
        self.is_a_duplicate = False

        # Create the log container which stores and handles incoming logs.
        self.log_view: LogView = LogView(self,
                                         self.application,
                                         log_store=log_store)

        # Log pane size variables. These are updated just befor rendering the
        # pane by the LogLineHSplit class.
        self.current_log_pane_width = 0
        self.current_log_pane_height = 0
        self.last_log_pane_width = None
        self.last_log_pane_height = None

        # Search tracking
        self.search_bar_active = False
        self.search_toolbar = SearchToolbar(self)
        self.filter_toolbar = FilterToolbar(self)

        self.saveas_dialog = LogPaneSaveAsDialog(self)
        self.saveas_dialog_active = False
        self.visual_selection_dialog = LogPaneSelectionDialog(self)

        # Table header bar, only shown if table view is active.
        self.table_header_toolbar = TableToolbar(self)

        # Create the bottom toolbar for the whole log pane.
        self.bottom_toolbar = WindowPaneToolbar(self)
        self.bottom_toolbar.add_button(
            ToolbarButton('/', 'Search', self.start_search))
        self.bottom_toolbar.add_button(
            ToolbarButton('Ctrl-o', 'Save', self.start_saveas))
        self.bottom_toolbar.add_button(
            ToolbarButton('f',
                          'Follow',
                          self.toggle_follow,
                          is_checkbox=True,
                          checked=lambda: self.log_view.follow))
        self.bottom_toolbar.add_button(
            ToolbarButton('t',
                          'Table',
                          self.toggle_table_view,
                          is_checkbox=True,
                          checked=lambda: self.table_view))
        self.bottom_toolbar.add_button(
            ToolbarButton('w',
                          'Wrap',
                          self.toggle_wrap_lines,
                          is_checkbox=True,
                          checked=lambda: self.wrap_lines))
        self.bottom_toolbar.add_button(
            ToolbarButton('C', 'Clear', self.clear_history))

        self.log_content_control = LogContentControl(self)

        self.log_display_window = Window(
            content=self.log_content_control,
            # Scrolling is handled by LogScreen
            allow_scroll_beyond_bottom=False,
            # Line wrapping is handled by LogScreen
            wrap_lines=False,
            # Selected line highlighting is handled by LogScreen
            cursorline=False,
            # Don't make the window taller to fill the parent split container.
            # Window should match the height of the log line content. This will
            # also allow the parent HSplit to justify the content to the bottom
            dont_extend_height=True,
            # Window width should be extended to make backround highlighting
            # extend to the end of the container. Otherwise backround colors
            # will only appear until the end of the log line.
            dont_extend_width=False,
            # Needed for log lines ANSI sequences that don't specify foreground
            # or background colors.
            style=functools.partial(pw_console.style.get_pane_style, self),
        )

        # Root level container
        self.container = ConditionalContainer(
            FloatContainer(
                # Horizonal split containing the log lines and the toolbar.
                WindowPaneHSplit(
                    self,  # LogPane reference
                    [
                        self.table_header_toolbar,
                        self.log_display_window,
                        self.filter_toolbar,
                        self.search_toolbar,
                        self.bottom_toolbar,
                    ],
                    # Align content with the bottom of the container.
                    align=VerticalAlign.BOTTOM,
                    height=lambda: self.height,
                    width=lambda: self.width,
                    style=functools.partial(pw_console.style.get_pane_style,
                                            self),
                ),
                floats=[
                    Float(top=0, right=0, height=1, content=LineInfoBar(self)),
                    Float(top=0,
                          right=0,
                          height=LogPaneSelectionDialog.DIALOG_HEIGHT,
                          content=self.visual_selection_dialog),
                    Float(top=3,
                          left=2,
                          right=2,
                          height=LogPaneSaveAsDialog.DIALOG_HEIGHT + 2,
                          content=self.saveas_dialog),
                ]),
            filter=Condition(lambda: self.show_pane))

    @property
    def table_view(self):
        return self._table_view

    @table_view.setter
    def table_view(self, table_view):
        self._table_view = table_view

    def menu_title(self):
        """Return the title to display in the Window menu."""
        title = self.pane_title()

        # List active filters
        if self.log_view.filtering_on:
            title += ' (FILTERS: '
            title += ' '.join([
                log_filter.pattern()
                for log_filter in self.log_view.filters.values()
            ])
            title += ')'
        return title

    def append_pane_subtitle(self, text):
        if not self._pane_subtitle:
            self._pane_subtitle = text
        else:
            self._pane_subtitle = self._pane_subtitle + ', ' + text

    def pane_subtitle(self) -> str:
        if not self._pane_subtitle:
            return ', '.join(self.log_view.log_store.channel_counts.keys())
        logger_names = self._pane_subtitle.split(', ')
        additional_text = ''
        if len(logger_names) > 1:
            additional_text = ' + {} more'.format(len(logger_names))

        return logger_names[0] + additional_text

    def start_search(self):
        """Show the search bar to begin a search."""
        # Show the search bar
        self.search_bar_active = True
        # Focus on the search bar
        self.application.focus_on_container(self.search_toolbar)

    def start_saveas(self, **export_kwargs) -> bool:
        """Show the saveas bar to begin saving logs to a file."""
        # Show the search bar
        self.saveas_dialog_active = True
        # Set export options if any
        self.saveas_dialog.set_export_options(**export_kwargs)
        # Focus on the search bar
        self.application.focus_on_container(self.saveas_dialog)
        return True

    def pane_resized(self) -> bool:
        """Return True if the current window size has changed."""
        return (self.last_log_pane_width != self.current_log_pane_width
                or self.last_log_pane_height != self.current_log_pane_height)

    def update_pane_size(self, width, height):
        """Save width and height of the log pane for the current UI render
        pass."""
        if width:
            self.last_log_pane_width = self.current_log_pane_width
            self.current_log_pane_width = width
        if height:
            # Subtract the height of the bottom toolbar
            height -= WindowPaneToolbar.TOOLBAR_HEIGHT
            if self._table_view:
                height -= TableToolbar.TOOLBAR_HEIGHT
            if self.search_bar_active:
                height -= SearchToolbar.TOOLBAR_HEIGHT
            if self.log_view.filtering_on:
                height -= FilterToolbar.TOOLBAR_HEIGHT
            self.last_log_pane_height = self.current_log_pane_height
            self.current_log_pane_height = height

    def toggle_table_view(self):
        """Enable or disable table view."""
        self._table_view = not self._table_view
        self.log_view.view_mode_changed()
        self.redraw_ui()

    def toggle_wrap_lines(self):
        """Enable or disable line wraping/truncation."""
        self.wrap_lines = not self.wrap_lines
        self.log_view.view_mode_changed()
        self.redraw_ui()

    def toggle_follow(self):
        """Enable or disable following log lines."""
        self.log_view.toggle_follow()
        self.redraw_ui()

    def clear_history(self):
        """Erase stored log lines."""
        self.log_view.clear_scrollback()
        self.redraw_ui()

    def get_all_key_bindings(self) -> List:
        """Return all keybinds for this pane."""
        # Return log content control keybindings
        return [self.log_content_control.get_key_bindings()]

    def get_window_menu_options(
            self) -> List[Tuple[str, Union[Callable, None]]]:
        """Return all menu options for the log pane."""

        options = [
            # Menu separator
            ('-', None),
            (
                'Save/Export a copy',
                self.start_saveas,
            ),
            ('-', None),
            (
                '{check} Line wrapping'.format(
                    check=pw_console.widgets.checkbox.to_checkbox_text(
                        self.wrap_lines, end='')),
                self.toggle_wrap_lines,
            ),
            (
                '{check} Table view'.format(
                    check=pw_console.widgets.checkbox.to_checkbox_text(
                        self._table_view, end='')),
                self.toggle_table_view,
            ),
            (
                '{check} Follow'.format(
                    check=pw_console.widgets.checkbox.to_checkbox_text(
                        self.log_view.follow, end='')),
                self.toggle_follow,
            ),
            # Menu separator
            ('-', None),
            (
                'Clear history',
                self.clear_history,
            ),
            (
                'Duplicate pane',
                self.duplicate,
            ),
        ]
        if self.is_a_duplicate:
            options += [(
                'Remove/Delete pane',
                functools.partial(self.application.window_manager.remove_pane,
                                  self),
            )]

        # Search / Filter section
        options += [
            # Menu separator
            ('-', None),
            (
                'Hide search highlighting',
                self.log_view.disable_search_highlighting,
            ),
            (
                'Create filter from search results',
                self.log_view.apply_filter,
            ),
            (
                'Clear/Reset active filters',
                self.log_view.clear_filters,
            ),
        ]

        return options

    def apply_filters_from_config(self, window_options) -> None:
        if 'filters' not in window_options:
            return

        for field, criteria in window_options['filters'].items():
            for matcher_name, search_string in criteria.items():
                inverted = matcher_name.endswith('-inverted')
                matcher_name = re.sub(r'-inverted$', '', matcher_name)
                if field == 'all':
                    field = None
                if self.log_view.new_search(
                        search_string,
                        invert=inverted,
                        field=field,
                        search_matcher=matcher_name,
                        interactive=False,
                ):
                    self.log_view.install_new_filter()

    def create_duplicate(self) -> 'LogPane':
        """Create a duplicate of this LogView."""
        new_pane = LogPane(self.application, pane_title=self.pane_title())
        # Set the log_store
        log_store = self.log_view.log_store
        new_pane.log_view.log_store = log_store
        # Register the duplicate pane as a viewer
        log_store.register_viewer(new_pane.log_view)

        # Set any existing search state.
        new_pane.log_view.search_text = self.log_view.search_text
        new_pane.log_view.search_filter = self.log_view.search_filter
        new_pane.log_view.search_matcher = self.log_view.search_matcher
        new_pane.log_view.search_highlight = self.log_view.search_highlight

        # Mark new pane as a duplicate so it can be deleted.
        new_pane.is_a_duplicate = True
        return new_pane

    def duplicate(self) -> None:
        new_pane = self.create_duplicate()
        # Add the new pane.
        self.application.window_manager.add_pane(new_pane)

    def add_log_handler(self,
                        logger: Union[str, logging.Logger],
                        level_name: Optional[str] = None) -> None:
        """Add a log handlers to this LogPane."""

        if isinstance(logger, logging.Logger):
            logger_instance = logger
        elif isinstance(logger, str):
            logger_instance = logging.getLogger(logger)

        if level_name:
            if not hasattr(logging, level_name):
                raise Exception(f'Unknown log level: {level_name}')
            logger_instance.level = getattr(logging, level_name, logging.INFO)
        logger_instance.addHandler(self.log_view.log_store  # type: ignore
                                   )
        self.append_pane_subtitle(  # type: ignore
            logger_instance.name)
