# 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.
"""SearchToolbar class used by LogPanes."""

from __future__ import annotations
import functools
from typing import TYPE_CHECKING

from prompt_toolkit.buffer import Buffer
from prompt_toolkit.filters import Condition, has_focus
from prompt_toolkit.formatted_text import StyleAndTextTuples
from prompt_toolkit.key_binding import (
    KeyBindings,
    KeyBindingsBase,
    KeyPressEvent,
)
from prompt_toolkit.layout import (
    ConditionalContainer,
    FormattedTextControl,
    HSplit,
    VSplit,
    Window,
    WindowAlign,
)
from prompt_toolkit.widgets import TextArea
from prompt_toolkit.validation import DynamicValidator

from pw_console.log_view import RegexValidator, SearchMatcher
# import pw_console.widgets.checkbox
import pw_console.widgets.mouse_handlers

if TYPE_CHECKING:
    from pw_console.log_pane import LogPane


class SearchToolbar(ConditionalContainer):
    """Toolbar for entering search text and viewing match counts."""

    TOOLBAR_HEIGHT = 2

    def __init__(self, log_pane: 'LogPane'):
        self.log_pane = log_pane
        self.log_view = log_pane.log_view
        self.search_validator = RegexValidator()
        self._search_successful = False
        self._search_invert = False
        self._search_field = None

        self.input_field = TextArea(
            prompt=[
                ('class:search-bar-setting', '/',
                 functools.partial(pw_console.widgets.mouse_handlers.on_click,
                                   self.focus_self))
            ],
            focusable=True,
            focus_on_click=True,
            scrollbar=False,
            multiline=False,
            height=1,
            dont_extend_height=True,
            dont_extend_width=False,
            accept_handler=self._search_accept_handler,
            validator=DynamicValidator(self.get_search_matcher),
            history=self.log_pane.application.search_history,
        )

        self.input_field.control.key_bindings = self._create_key_bindings()

        match_count_window = Window(
            content=FormattedTextControl(self.get_match_count_fragments),
            height=1,
            align=WindowAlign.LEFT,
            dont_extend_width=True,
            style='class:search-match-count-dialog',
        )

        match_buttons_window = Window(
            content=FormattedTextControl(self.get_button_fragments),
            height=1,
            align=WindowAlign.LEFT,
            dont_extend_width=False,
            style='class:search-match-count-dialog',
        )

        input_field_buttons_window = Window(
            content=FormattedTextControl(self.get_search_help_fragments),
            height=1,
            align=WindowAlign.RIGHT,
            dont_extend_width=True,
        )

        settings_bar_window = Window(
            content=FormattedTextControl(self.get_search_settings_fragments),
            height=1,
            align=WindowAlign.LEFT,
            dont_extend_width=False,
        )

        super().__init__(
            HSplit(
                [
                    # Top row
                    VSplit([
                        # Search Settings toggles, only show if the search input
                        # field is in focus.
                        ConditionalContainer(settings_bar_window,
                                             filter=has_focus(
                                                 self.input_field)),

                        # Match count numbers and buttons, only show if the
                        # search input is NOT in focus.
                        ConditionalContainer(
                            match_count_window,
                            filter=~has_focus(self.input_field)),  # pylint: disable=invalid-unary-operand-type
                        ConditionalContainer(
                            match_buttons_window,
                            filter=~has_focus(self.input_field)),  # pylint: disable=invalid-unary-operand-type
                    ]),
                    # Bottom row
                    VSplit([
                        self.input_field,
                        ConditionalContainer(input_field_buttons_window,
                                             filter=has_focus(self))
                    ])
                ],
                height=SearchToolbar.TOOLBAR_HEIGHT,
                style='class:search-bar',
            ),
            filter=Condition(lambda: log_pane.search_bar_active),
        )

    def _create_key_bindings(self) -> KeyBindingsBase:
        """Create additional key bindings for the search input."""
        # Clear filter keybind is handled by the parent log_pane.

        key_bindings = KeyBindings()
        register = self.log_pane.application.prefs.register_keybinding

        @register('search-toolbar.cancel', key_bindings)
        def _close_search_bar(_event: KeyPressEvent) -> None:
            """Close search bar."""
            self.cancel_search()

        @register('search-toolbar.toggle-matcher', key_bindings)
        def _select_next_search_matcher(_event: KeyPressEvent) -> None:
            """Select the next search matcher."""
            self.log_pane.log_view.select_next_search_matcher()

        @register('search-toolbar.create-filter', key_bindings)
        def _create_filter(_event: KeyPressEvent) -> None:
            """Create a filter."""
            self.create_filter()

        @register('search-toolbar.toggle-invert', key_bindings)
        def _toggle_search_invert(_event: KeyPressEvent) -> None:
            """Toggle inverted search matching."""
            self._invert_search()

        @register('search-toolbar.toggle-column', key_bindings)
        def _select_next_field(_event: KeyPressEvent) -> None:
            """Select next search field/column."""
            self._next_field()

        return key_bindings

    def focus_self(self) -> None:
        self.log_pane.application.application.layout.focus(self)

    def focus_log_pane(self) -> None:
        self.log_pane.application.focus_on_container(self.log_pane)

    def _create_filter(self) -> None:
        self.input_field.buffer.reset()
        self.close_search_bar()
        self.log_view.apply_filter()

    def _next_match(self) -> None:
        self.log_view.search_forwards()

    def _previous_match(self) -> None:
        self.log_view.search_backwards()

    def cancel_search(self) -> None:
        self.input_field.buffer.reset()
        self.close_search_bar()
        self.log_view.clear_search()

    def close_search_bar(self) -> None:
        """Close search bar."""
        # Reset invert setting for the next search
        self._search_invert = False
        self.log_view.follow_search_match = False
        # Hide the search bar
        self.log_pane.search_bar_active = False
        # Focus on the log_pane.
        self.log_pane.application.focus_on_container(self.log_pane)
        self.log_pane.redraw_ui()

    def _start_search(self) -> None:
        self.input_field.buffer.validate_and_handle()

    def _invert_search(self) -> None:
        self._search_invert = not self._search_invert

    def _toggle_search_follow(self) -> None:
        self.log_view.follow_search_match = (
            not self.log_view.follow_search_match)
        # If automatically jumping to the next search match, disable normal
        # follow mode.
        if self.log_view.follow_search_match:
            self.log_view.follow = False

    def _next_field(self) -> None:
        fields = self.log_pane.log_view.log_store.table.all_column_names()
        fields.append(None)
        current_index = fields.index(self._search_field)
        next_index = (current_index + 1) % len(fields)
        self._search_field = fields[next_index]

    def create_filter(self) -> None:
        self._start_search()
        if self._search_successful:
            self.log_pane.log_view.apply_filter()

    def _search_accept_handler(self, buff: Buffer) -> bool:
        """Function run when hitting Enter in the search bar."""
        self._search_successful = False
        if len(buff.text) == 0:
            self.close_search_bar()
            # Don't apply an empty search.
            return False

        if self.log_pane.log_view.new_search(buff.text,
                                             invert=self._search_invert,
                                             field=self._search_field):
            self._search_successful = True

            # Don't close the search bar, instead focus on the log content.
            self.log_pane.application.focus_on_container(
                self.log_pane.log_display_window)
            # Keep existing search text.
            return True

        # Keep existing text if regex error
        return True

    def get_search_help_fragments(self):
        """Return FormattedText with search general help keybinds."""
        focus = functools.partial(pw_console.widgets.mouse_handlers.on_click,
                                  self.focus_self)
        start_search = functools.partial(
            pw_console.widgets.mouse_handlers.on_click, self._start_search)
        close_search = functools.partial(
            pw_console.widgets.mouse_handlers.on_click, self.cancel_search)

        # Search toolbar is darker than pane toolbars, use the darker button
        # style here.
        button_style = 'class:toolbar-button-inactive'

        separator_text = [('', '  ', focus)]

        # Empty text matching the width of the search bar title.
        fragments = [
            ('', '        ', focus),
        ]
        fragments.extend(separator_text)

        fragments.extend(
            pw_console.widgets.checkbox.to_keybind_indicator(
                'Enter', 'Search', start_search, base_style=button_style))
        fragments.extend(separator_text)

        fragments.extend(
            pw_console.widgets.checkbox.to_keybind_indicator(
                'Ctrl-c', 'Cancel', close_search, base_style=button_style))

        return fragments

    def get_search_settings_fragments(self):
        """Return FormattedText with current search settings and keybinds."""
        focus = functools.partial(pw_console.widgets.mouse_handlers.on_click,
                                  self.focus_self)
        next_field = functools.partial(
            pw_console.widgets.mouse_handlers.on_click, self._next_field)
        toggle_invert = functools.partial(
            pw_console.widgets.mouse_handlers.on_click, self._invert_search)
        next_matcher = functools.partial(
            pw_console.widgets.mouse_handlers.on_click,
            self.log_pane.log_view.select_next_search_matcher)

        separator_text = [('', '  ', focus)]

        # Search toolbar is darker than pane toolbars, use the darker button
        # style here.
        button_style = 'class:toolbar-button-inactive'

        fragments = [
            # Title
            ('class:search-bar-title', ' Search ', focus),
        ]
        fragments.extend(separator_text)

        selected_column_text = [
            (button_style + ' class:search-bar-setting',
             (self._search_field.title() if self._search_field else 'All'),
             next_field),
        ]
        fragments.extend(
            pw_console.widgets.checkbox.to_keybind_indicator(
                'Ctrl-t',
                'Column:',
                next_field,
                middle_fragments=selected_column_text,
                base_style=button_style,
            ))
        fragments.extend(separator_text)

        fragments.extend(
            pw_console.widgets.checkbox.to_checkbox_with_keybind_indicator(
                self._search_invert,
                'Ctrl-v',
                'Invert',
                toggle_invert,
                base_style=button_style))
        fragments.extend(separator_text)

        # Matching Method
        current_matcher_text = [
            (button_style + ' class:search-bar-setting',
             str(self.log_pane.log_view.search_matcher.name), next_matcher)
        ]
        fragments.extend(
            pw_console.widgets.checkbox.to_keybind_indicator(
                'Ctrl-n',
                'Matcher:',
                next_matcher,
                middle_fragments=current_matcher_text,
                base_style=button_style,
            ))
        fragments.extend(separator_text)

        return fragments

    def get_search_matcher(self):
        if self.log_pane.log_view.search_matcher == SearchMatcher.REGEX:
            return self.log_pane.log_view.search_validator
        return False

    def get_match_count_fragments(self):
        """Return formatted text for the match count indicator."""
        focus = functools.partial(pw_console.widgets.mouse_handlers.on_click,
                                  self.focus_log_pane)
        two_spaces = ('', '  ', focus)

        # Check if this line is a search match
        match_number = self.log_view.search_matched_lines.get(
            self.log_view.log_index, -1)

        # If valid, increment the zero indexed value by one for better human
        # readability.
        if match_number >= 0:
            match_number += 1
        # If no match, mark as zero
        else:
            match_number = 0

        return [
            ('class:search-match-count-dialog-title', ' Match ', focus),
            ('', '{} / {}'.format(match_number,
                                  len(self.log_view.search_matched_lines)),
             focus),
            two_spaces,
        ]

    def get_button_fragments(self) -> StyleAndTextTuples:
        """Return formatted text for the action buttons."""
        focus = functools.partial(pw_console.widgets.mouse_handlers.on_click,
                                  self.focus_log_pane)

        one_space = ('', ' ', focus)
        two_spaces = ('', '  ', focus)
        cancel = functools.partial(pw_console.widgets.mouse_handlers.on_click,
                                   self.cancel_search)
        create_filter = functools.partial(
            pw_console.widgets.mouse_handlers.on_click, self._create_filter)
        next_match = functools.partial(
            pw_console.widgets.mouse_handlers.on_click, self._next_match)
        previous_match = functools.partial(
            pw_console.widgets.mouse_handlers.on_click, self._previous_match)
        toggle_search_follow = functools.partial(
            pw_console.widgets.mouse_handlers.on_click,
            self._toggle_search_follow)

        button_style = 'class:toolbar-button-inactive'

        fragments = []
        fragments.extend(
            pw_console.widgets.checkbox.to_keybind_indicator(
                key='n',
                description='Next',
                mouse_handler=next_match,
                base_style=button_style,
            ))
        fragments.append(two_spaces)

        fragments.extend(
            pw_console.widgets.checkbox.to_keybind_indicator(
                key='N',
                description='Previous',
                mouse_handler=previous_match,
                base_style=button_style,
            ))
        fragments.append(two_spaces)

        fragments.extend(
            pw_console.widgets.checkbox.to_keybind_indicator(
                key='Ctrl-c',
                description='Cancel',
                mouse_handler=cancel,
                base_style=button_style,
            ))
        fragments.append(two_spaces)

        fragments.extend(
            pw_console.widgets.checkbox.to_keybind_indicator(
                key='Ctrl-Alt-f',
                description='Add Filter',
                mouse_handler=create_filter,
                base_style=button_style,
            ))
        fragments.append(two_spaces)

        fragments.extend(
            pw_console.widgets.checkbox.to_checkbox_with_keybind_indicator(
                checked=self.log_view.follow_search_match,
                key='',
                description='Jump to new matches',
                mouse_handler=toggle_search_follow,
                base_style=button_style))
        fragments.append(one_space)

        return fragments
