# 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.
# pylint: skip-file
"""Console key bindings."""
import logging

from prompt_toolkit.filters import (
    Condition,
    has_focus,
)
from prompt_toolkit.key_binding import KeyBindings
from prompt_toolkit.key_binding.bindings.focus import focus_next, focus_previous

import pw_console.pw_ptpython_repl

__all__ = ('create_key_bindings', )

_LOG = logging.getLogger(__package__)


def create_key_bindings(console_app):
    """Create custom key bindings.

    This starts with the key bindings, defined by `prompt-toolkit`, but adds the
    ones which are specific for the console_app. A console_app instance
    reference is passed in so key bind functions can access it.
    """

    bindings = KeyBindings()

    @bindings.add(
        'f1', filter=Condition(lambda: not console_app.modal_window_is_open()))
    def show_help(event):
        """Toggle user guide window."""
        console_app.user_guide_window.toggle_display()

    # F2 is ptpython settings
    # F3 is ptpython history

    @bindings.add('c-q')
    def exit_(event):
        """Quit the console application."""
        # TODO(tonymd): Cancel any existing user repl or plugin tasks before
        # exiting.
        event.app.exit()

    @bindings.add('c-left')
    def app_focus_previous(event):
        """Move focus to the previous widget."""
        focus_previous(event)

    @bindings.add('s-tab')
    @bindings.add('c-right')
    def app_focus_next(event):
        """Move focus to the next widget."""
        focus_next(event)

    # Bindings for when the ReplPane input field is in focus.
    # These are hidden from help window global keyboard shortcuts since the
    # method names end with `_hidden`.
    @bindings.add('c-c', filter=has_focus(console_app.pw_ptpython_repl))
    def handle_ctrl_c_hidden(event):
        """Reset the python repl on Ctrl-c"""
        console_app.repl_pane.ctrl_c()

    @bindings.add('c-d',
                  filter=console_app.pw_ptpython_repl.
                  has_focus_and_input_empty_condition())
    def handle_ctrl_d_hidden(event):
        """Do nothing on ctrl-d."""
        # TODO(tonymd): Ctrl-d should quit the whole app with confirmation.
        # Ctrl-d in ptpython repl prompts y/n to quit if the input is empty. If
        # not empty, it deletes forward characters. This binding should block
        # ctrl-d if the input is empty. The quit confirmation dialog breaks the
        # ptpython state and further repl invocations.
        pass

    @bindings.add('c-v', filter=has_focus(console_app.pw_ptpython_repl))
    def paste_into_repl(event):
        """Reset the python repl on Ctrl-c"""
        console_app.repl_pane.paste_system_clipboard_to_input_buffer()

    @bindings.add(
        'escape',
        'c-c',  # Alt-Ctrl-c
        filter=console_app.repl_pane.input_or_output_has_focus())
    def paste_into_repl(event):
        """Copy all Python output to the system clipboard."""
        console_app.repl_pane.copy_text()

    return bindings
