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

from __future__ import annotations
import functools
from typing import TYPE_CHECKING

from prompt_toolkit.filters import Condition
from prompt_toolkit.layout import (
    ConditionalContainer,
    FormattedTextControl,
    VSplit,
    Window,
    WindowAlign,
    HorizontalAlign,
)
from prompt_toolkit.mouse_events import MouseEvent, MouseEventType

import pw_console.widgets.checkbox
import pw_console.widgets.mouse_handlers
import pw_console.style

if TYPE_CHECKING:
    from pw_console.log_pane import LogPane


class FilterToolbar(ConditionalContainer):
    """Container showing each filter applied in order."""

    TOOLBAR_HEIGHT = 1

    def mouse_handler_delete_filter(self, filter_text,
                                    mouse_event: MouseEvent):
        """Delete the given log filter."""
        if mouse_event.event_type == MouseEventType.MOUSE_UP:
            self.log_pane.log_view.delete_filter(filter_text)
            return None
        return NotImplemented

    def get_left_fragments(self):
        """Return formatted text tokens for display."""
        separator = ('', '  ')
        space = ('', ' ')
        fragments = [('class:filter-bar-title', ' Filters '), separator]

        button_style = pw_console.style.get_button_style(self.log_pane)

        for filter_text, log_filter in self.log_pane.log_view.filters.items():
            fragments.append(('class:filter-bar-delimiter', '<'))

            if log_filter.invert:
                fragments.append(('class:filter-bar-setting', 'NOT '))

            if log_filter.field:
                fragments.append(
                    ('class:filter-bar-setting', log_filter.field))
                fragments.append(space)

            fragments.append(('', filter_text))
            fragments.append(space)

            fragments.append(
                (button_style + ' class:filter-bar-delete', ' (X) ',
                 functools.partial(self.mouse_handler_delete_filter,
                                   filter_text)))  # type: ignore
            fragments.append(('class:filter-bar-delimiter', '>'))

            fragments.append(separator)
        return fragments

    def get_center_fragments(self):
        """Return formatted text tokens for display."""
        clear_filters = functools.partial(
            pw_console.widgets.mouse_handlers.on_click,
            self.log_pane.log_view.clear_filters)

        button_style = pw_console.style.get_button_style(self.log_pane)

        return pw_console.widgets.checkbox.to_keybind_indicator(
            'Ctrl-Alt-r',
            'Clear Filters',
            clear_filters,
            base_style=button_style)

    def __init__(self, log_pane: 'LogPane'):
        self.log_pane = log_pane
        left_bar_control = FormattedTextControl(self.get_left_fragments)
        left_bar_window = Window(content=left_bar_control,
                                 align=WindowAlign.LEFT,
                                 dont_extend_width=True)
        center_bar_control = FormattedTextControl(self.get_center_fragments)
        center_bar_window = Window(content=center_bar_control,
                                   align=WindowAlign.LEFT,
                                   dont_extend_width=False)
        super().__init__(
            VSplit(
                [
                    left_bar_window,
                    center_bar_window,
                ],
                style=functools.partial(pw_console.style.get_toolbar_style,
                                        self.log_pane,
                                        dim=True),
                height=1,
                align=HorizontalAlign.LEFT,
            ),
            # Only show if filtering is enabled.
            filter=Condition(lambda: self.log_pane.log_view.filtering_on),
        )
