# 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.
"""Window pane toolbar base class."""

import logging
from typing import Any, Callable, List, Optional
import functools

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

from pw_console.get_pw_console_app import get_pw_console_app
import pw_console.style
from pw_console.widgets import (
    ToolbarButton,
    to_checkbox_with_keybind_indicator,
    to_keybind_indicator,
)
import pw_console.widgets.mouse_handlers

_LOG = logging.getLogger(__package__)


class WindowPaneResizeHandle(FormattedTextControl):
    """Button to initiate window pane resize drag events."""
    def __init__(self, parent_window_pane: Any, *args, **kwargs) -> None:
        self.parent_window_pane = parent_window_pane
        super().__init__(*args, **kwargs)

    def mouse_handler(self, mouse_event: MouseEvent):
        """Mouse handler for this control."""
        # Start resize mouse drag event
        if mouse_event.event_type == MouseEventType.MOUSE_DOWN:
            get_pw_console_app().window_manager.start_resize_pane(
                self.parent_window_pane)
            # Mouse event handled, return None.
            return None

        # Mouse event not handled, return NotImplemented.
        return NotImplemented


class WindowPaneToolbar:
    """One line toolbar for display at the bottom of of a window pane."""
    # pylint: disable=too-many-instance-attributes
    TOOLBAR_HEIGHT = 1

    def get_left_text_tokens(self):
        """Return toolbar indicator and title."""

        title = self.title
        if not title and self.parent_window_pane:
            # No title was set, fetch the parent window pane title if available.
            parent_pane_title = self.parent_window_pane.pane_title()
            title = parent_pane_title if parent_pane_title else title
        return pw_console.style.get_pane_indicator(self.focus_check_container,
                                                   f' {title} ',
                                                   self.focus_mouse_handler)

    def get_center_text_tokens(self):
        """Return formatted text tokens for display in the center part of the
        toolbar."""

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

        # FormattedTextTuple contents: (Style, Text, Mouse handler)
        separator_text = [('', '  ')
                          ]  # 2 spaces of separaton between keybinds.
        if self.focus_mouse_handler:
            separator_text = [('', '  ', self.focus_mouse_handler)]

        fragments = []
        fragments.extend(separator_text)

        for button in self.buttons:
            on_click_handler = None
            if button.mouse_handler:
                on_click_handler = functools.partial(
                    pw_console.widgets.mouse_handlers.on_click,
                    button.mouse_handler)

            if button.is_checkbox:
                fragments.extend(
                    to_checkbox_with_keybind_indicator(
                        button.checked(),
                        button.key,
                        button.description,
                        on_click_handler,
                        base_style=button_style))
            else:
                fragments.extend(
                    to_keybind_indicator(button.key,
                                         button.description,
                                         on_click_handler,
                                         base_style=button_style))

            fragments.extend(separator_text)

        # Remaining whitespace should focus on click.
        fragments.extend(separator_text)

        return fragments

    def get_right_text_tokens(self):
        """Return formatted text tokens for display."""
        fragments = []
        if not has_focus(self.focus_check_container.__pt_container__())():
            fragments.append((
                'class:toolbar-button-inactive class:toolbar-button-decoration',
                ' ', self.focus_mouse_handler))
            fragments.append(('class:toolbar-button-inactive class:keyhelp',
                              'click to focus', self.focus_mouse_handler))
            fragments.append((
                'class:toolbar-button-inactive class:toolbar-button-decoration',
                ' ', self.focus_mouse_handler))
        fragments.append(
            ('', '  {} '.format(self.subtitle()), self.focus_mouse_handler))
        return fragments

    def get_resize_handle(self):
        return pw_console.style.get_pane_indicator(self.focus_check_container,
                                                   '─══─',
                                                   hide_indicator=True)

    def add_button(self, button: ToolbarButton):
        self.buttons.append(button)

    def __init__(
        self,
        parent_window_pane: Optional[Any] = None,
        title: Optional[str] = None,
        subtitle: Optional[Callable[[], str]] = None,
        focus_check_container: Optional[Any] = None,
        focus_action_callable: Optional[Callable] = None,
        center_section_align: WindowAlign = WindowAlign.LEFT,
        include_resize_handle: bool = True,
    ):

        self.parent_window_pane = parent_window_pane
        self.title = title
        self.subtitle = subtitle

        # Assume check this container for focus
        self.focus_check_container = self
        self.focus_action_callable = None

        # Set parent_window_pane related options
        if self.parent_window_pane:
            if not subtitle:
                self.subtitle = self.parent_window_pane.pane_subtitle
            self.focus_check_container = self.parent_window_pane
            self.focus_action_callable = self.parent_window_pane.focus_self

        # Set title overrides
        if self.subtitle is None:

            def empty_subtitle() -> str:
                return ''

            self.subtitle = empty_subtitle

        if focus_check_container:
            self.focus_check_container = focus_check_container
        if focus_action_callable:
            self.focus_action_callable = focus_action_callable

        self.focus_mouse_handler = None
        if self.focus_action_callable:
            self.focus_mouse_handler = functools.partial(
                pw_console.widgets.mouse_handlers.on_click,
                self.focus_action_callable)

        self.buttons: List[ToolbarButton] = []
        self.show_toolbar = True

        self.left_section_window = Window(
            content=FormattedTextControl(self.get_left_text_tokens),
            align=WindowAlign.LEFT,
            dont_extend_width=True,
        )

        self.center_section_window = Window(
            content=FormattedTextControl(self.get_center_text_tokens),
            align=center_section_align,
            dont_extend_width=False,
        )

        self.right_section_window = Window(
            content=FormattedTextControl(self.get_right_text_tokens),
            # Right side text should appear at the far right of the toolbar
            align=WindowAlign.RIGHT,
            dont_extend_width=True,
        )

        get_toolbar_style = functools.partial(
            pw_console.style.get_toolbar_style, self.focus_check_container)

        sections = [
            self.left_section_window,
            self.center_section_window,
            self.right_section_window,
        ]
        if self.parent_window_pane and include_resize_handle:
            resize_handle = Window(
                content=WindowPaneResizeHandle(
                    self.parent_window_pane,
                    self.get_resize_handle,
                ),
                # Right side text should appear at the far right of the toolbar
                align=WindowAlign.RIGHT,
                dont_extend_width=True,
            )
            sections.append(resize_handle)

        self.toolbar_vsplit = VSplit(
            sections,
            height=WindowPaneToolbar.TOOLBAR_HEIGHT,
            style=get_toolbar_style,
        )

        self.container = self._create_toolbar_container(self.toolbar_vsplit)

    def _create_toolbar_container(self, content):
        return ConditionalContainer(
            content, filter=Condition(lambda: self.show_toolbar))

    def __pt_container__(self):
        """Return the prompt_toolkit root container for this log pane.

        This allows self to be used wherever prompt_toolkit expects a container
        object."""
        return self.container  # pylint: disable=no-member
