# 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.
"""LogPane Info Toolbar classes."""

from __future__ import annotations
import functools
import logging
import sys
from typing import Optional, Callable, TYPE_CHECKING

from prompt_toolkit.data_structures import Point
from prompt_toolkit.key_binding import KeyBindings, KeyPressEvent
from prompt_toolkit.filters import Condition
from prompt_toolkit.layout import (
    ConditionalContainer,
    FormattedTextControl,
    HSplit,
    Window,
    WindowAlign,
)

import pw_console.widgets.border
import pw_console.widgets.checkbox
import pw_console.widgets.mouse_handlers

if TYPE_CHECKING:
    from pw_console.console_app import ConsoleApp

_LOG = logging.getLogger(__package__)


class QuitDialog(ConditionalContainer):
    """Confirmation quit dialog box."""

    DIALOG_HEIGHT = 2

    def __init__(self,
                 application: ConsoleApp,
                 on_quit: Optional[Callable] = None):
        self.application = application
        self.show_dialog = False
        # Tracks the last focused container, to enable restoring focus after
        # closing the dialog.
        self.last_focused_pane = None

        self.on_quit_function = (on_quit if on_quit else
                                 self._default_on_quit_function)

        # Quit keybindings are active when this dialog is in focus
        key_bindings = KeyBindings()
        register = self.application.prefs.register_keybinding

        @register('quit-dialog.yes', key_bindings)
        def _quit(_event: KeyPressEvent) -> None:
            """Close save as bar."""
            self.quit_action()

        @register('quit-dialog.no', key_bindings)
        def _cancel(_event: KeyPressEvent) -> None:
            """Close save as bar."""
            self.close_dialog()

        self.exit_message = 'Quit? y/n '

        action_bar_control = FormattedTextControl(
            self.get_action_fragments,
            show_cursor=True,
            focusable=True,
            key_bindings=key_bindings,
            # Cursor will appear after the exit_message
            get_cursor_position=lambda: Point(len(self.exit_message), 0),
        )

        action_bar_window = Window(content=action_bar_control,
                                   height=QuitDialog.DIALOG_HEIGHT,
                                   align=WindowAlign.LEFT,
                                   dont_extend_width=False)

        super().__init__(
            pw_console.widgets.border.create_border(
                HSplit(
                    [action_bar_window],
                    height=QuitDialog.DIALOG_HEIGHT,
                    style='class:quit-dialog',
                ),
                QuitDialog.DIALOG_HEIGHT,
                border_style='class:quit-dialog-border',
                left_margin_columns=1,
            ),
            filter=Condition(lambda: self.show_dialog),
        )

    def focus_self(self):
        self.application.layout.focus(self)

    def close_dialog(self):
        """Close this dialog box."""
        self.show_dialog = False
        # Restore original focus if possible.
        if self.last_focused_pane:
            self.application.layout.focus(self.last_focused_pane)
        else:
            # Fallback to focusing on the main menu.
            self.application.focus_main_menu()

    def open_dialog(self):
        self.show_dialog = True
        self.last_focused_pane = self.application.focused_window()
        self.focus_self()
        self.application.redraw_ui()

    def _default_on_quit_function(self):
        if hasattr(self.application, 'application'):
            self.application.application.exit()
        else:
            sys.exit()

    def quit_action(self):
        self.on_quit_function()

    def get_action_fragments(self):
        """Return FormattedText with action buttons."""

        # Mouse handlers
        focus = functools.partial(pw_console.widgets.mouse_handlers.on_click,
                                  self.focus_self)
        cancel = functools.partial(pw_console.widgets.mouse_handlers.on_click,
                                   self.close_dialog)
        quit_action = functools.partial(
            pw_console.widgets.mouse_handlers.on_click, self.quit_action)

        # Separator should have the focus mouse handler so clicking on any
        # whitespace focuses the input field.
        separator_text = ('', '  ', focus)

        # Default button style
        button_style = 'class:toolbar-button-inactive'

        fragments = [('', self.exit_message), separator_text]
        fragments.append(('', '\n'))

        # Cancel button
        fragments.extend(
            pw_console.widgets.checkbox.to_keybind_indicator(
                key='n / Ctrl-c',
                description='Cancel',
                mouse_handler=cancel,
                base_style=button_style,
            ))

        # Two space separator
        fragments.append(separator_text)

        # Save button
        fragments.extend(
            pw_console.widgets.checkbox.to_keybind_indicator(
                key='y / Ctrl-d',
                description='Quit',
                mouse_handler=quit_action,
                base_style=button_style,
            ))

        # One space separator
        fragments.append(('', ' ', focus))

        return fragments
