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

import asyncio
import logging
from pathlib import Path
from typing import Any, Dict, List, Iterable, Optional, Tuple, Union

from prompt_toolkit.completion import WordCompleter

from pw_console.console_app import ConsoleApp
from pw_console.get_pw_console_app import PW_CONSOLE_APP_CONTEXTVAR
from pw_console.plugin_mixin import PluginMixin
import pw_console.python_logging
from pw_console.widgets import (
    FloatingWindowPane,
    WindowPane,
    WindowPaneToolbar,
)


def _set_console_app_instance(plugin: Any, console_app: ConsoleApp) -> None:
    if hasattr(plugin, 'pw_console_init'):
        plugin.pw_console_init(console_app)
    else:
        plugin.application = console_app


class PwConsoleEmbed:
    """Embed class for customizing the console before startup."""

    # pylint: disable=too-many-instance-attributes
    def __init__(self,
                 global_vars=None,
                 local_vars=None,
                 loggers: Optional[Union[Dict[str, Iterable[logging.Logger]],
                                         Iterable]] = None,
                 test_mode=False,
                 repl_startup_message: Optional[str] = None,
                 help_text: Optional[str] = None,
                 app_title: Optional[str] = None,
                 config_file_path: Optional[Union[str, Path]] = None) -> None:
        """Call this to embed pw console at the call point within your program.

        Example usage:

        .. code-block:: python

            import logging

            from pw_console import PwConsoleEmbed

            # Create the pw_console embed instance
            console = PwConsoleEmbed(
                global_vars=globals(),
                local_vars=locals(),
                loggers={
                    'Host Logs': [
                        logging.getLogger(__package__),
                        logging.getLogger(__name__),
                    ],
                    'Device Logs': [
                        logging.getLogger('usb_gadget'),
                    ],
                },
                app_title='My Awesome Console',
                config_file_path='/home/user/project/.pw_console.yaml',
            )
            # Optional: Add custom completions
            console.add_sentence_completer(
                {
                    'some_function', 'Function',
                    'some_variable', 'Variable',
                }
            )

            # Setup Python loggers to output to a file instead of STDOUT.
            console.setup_python_logging()

            # Then run the console with:
            console.embed()

        Args:
            global_vars: Dictionary representing the desired global symbol
                table. Similar to what is returned by `globals()`.
            local_vars: Dictionary representing the desired local symbol
                table. Similar to what is returned by `locals()`.
            loggers: Dict with keys of log window titles and values of either:

                    1. List of `logging.getLogger()
                       <https://docs.python.org/3/library/logging.html#logging.getLogger>`_
                       instances.
                    2. A single pw_console.log_store.LogStore instance.

            app_title: Custom title text displayed in the user interface.
            repl_startup_message: Custom text shown by default in the repl
                output pane.
            help_text: Custom text shown at the top of the help window before
                keyboard shortcuts.
            config_file_path: Path to a pw_console yaml config file.
        """

        self.global_vars = global_vars
        self.local_vars = local_vars
        self.loggers = loggers
        self.test_mode = test_mode
        self.repl_startup_message = repl_startup_message
        self.help_text = help_text
        self.app_title = app_title
        self.config_file_path = Path(
            config_file_path) if config_file_path else None

        self.console_app: Optional[ConsoleApp] = None
        self.extra_completers: List = []

        self.setup_python_logging_called = False
        self.hidden_by_default_windows: List[str] = []
        self.window_plugins: List[WindowPane] = []
        self.floating_window_plugins: List[Tuple[FloatingWindowPane,
                                                 Dict]] = []
        self.top_toolbar_plugins: List[WindowPaneToolbar] = []
        self.bottom_toolbar_plugins: List[WindowPaneToolbar] = []

    def add_window_plugin(self, window_pane: WindowPane) -> None:
        """Include a custom window pane plugin.

        Args:
            window_pane: Any instance of the WindowPane class.
        """
        self.window_plugins.append(window_pane)

    def add_floating_window_plugin(self, window_pane: FloatingWindowPane,
                                   **float_args) -> None:
        """Include a custom floating window pane plugin.

        This adds a FloatingWindowPane class to the pw_console UI. The first
        argument should be the window to add and the remaining keyword arguments
        are passed to the prompt_toolkit Float() class. This allows positioning
        of the floating window. By default the floating window will be
        centered. To anchor the window to a side or corner of the screen set the
        ``left``, ``right``, ``top``, or ``bottom`` keyword args.

        For example:

        .. code-block:: python

           from pw_console import PwConsoleEmbed

           console = PwConsoleEmbed(...)
           my_plugin = MyPlugin()
           # Anchor this floating window 2 rows away from the top and 4 columns
           # away from the left edge of the screen.
           console.add_floating_window_plugin(my_plugin, top=2, left=4)

        See all possible keyword args in the prompt_toolkit documentation:
        https://python-prompt-toolkit.readthedocs.io/en/stable/pages/reference.html#prompt_toolkit.layout.Float

        Args:
            window_pane: Any instance of the FloatingWindowPane class.
            left: Distance to the left edge of the screen
            right: Distance to the right edge of the screen
            top: Distance to the top edge of the screen
            bottom: Distance to the bottom edge of the screen
        """
        self.floating_window_plugins.append((window_pane, float_args))

    def add_top_toolbar(self, toolbar: WindowPaneToolbar) -> None:
        """Include a toolbar plugin to display on the top of the screen.

        Top toolbars appear above all window panes and just below the main menu
        bar. They span the full width of the screen.

        Args:
            toolbar: Instance of the WindowPaneToolbar class.
        """
        self.top_toolbar_plugins.append(toolbar)

    def add_bottom_toolbar(self, toolbar: WindowPaneToolbar) -> None:
        """Include a toolbar plugin to display at the bottom of the screen.

        Bottom toolbars appear below all window panes and span the full width of
        the screen.

        Args:
            toolbar: Instance of the WindowPaneToolbar class.
        """
        self.bottom_toolbar_plugins.append(toolbar)

    def add_sentence_completer(self,
                               word_meta_dict: Dict[str, str],
                               ignore_case=True) -> None:
        """Include a custom completer that matches on the entire repl input.

        Args:
            word_meta_dict: Dictionary representing the sentence completions
                and descriptions. Keys are completion text, values are
                descriptions.
        """

        # Don't modify completion if empty.
        if len(word_meta_dict) == 0:
            return

        sentences: List[str] = list(word_meta_dict.keys())
        word_completer = WordCompleter(
            sentences,
            meta_dict=word_meta_dict,
            ignore_case=ignore_case,
            # Whole input field should match
            sentence=True,
        )

        self.extra_completers.append(word_completer)

    def _setup_log_panes(self) -> None:
        """Add loggers to ConsoleApp log pane(s)."""
        if not self.loggers:
            return

        assert isinstance(self.console_app, ConsoleApp)

        if isinstance(self.loggers, list):
            self.console_app.add_log_handler('Logs', self.loggers)

        elif isinstance(self.loggers, dict):
            for window_title, logger_instances in self.loggers.items():
                window_pane = self.console_app.add_log_handler(
                    window_title, logger_instances)

                if (window_pane and window_pane.pane_title()
                        in self.hidden_by_default_windows):
                    window_pane.show_pane = False

    def setup_python_logging(
        self,
        last_resort_filename: Optional[str] = None,
        loggers_with_no_propagation: Optional[Iterable[logging.Logger]] = None
    ) -> None:
        """Setup friendly logging for full-screen prompt_toolkit applications.

        This function sets up Python log handlers to be friendly for full-screen
        prompt_toolkit applications. That is, logging to terminal STDOUT and
        STDERR is disabled so the terminal user interface can be drawn.

        Specifically, all Python STDOUT and STDERR log handlers are
        disabled. It also sets `log propagation to True
        <https://docs.python.org/3/library/logging.html#logging.Logger.propagate>`_.
        to ensure that all log messages are sent to the root logger.

        Args:
            last_resort_filename: If specified use this file as a fallback for
                unhandled Python logging messages. Normally Python will output
                any log messages with no handlers to STDERR as a fallback. If
                None, a temp file will be created instead. See Python
                documentation on `logging.lastResort
                <https://docs.python.org/3/library/logging.html#logging.lastResort>`_
                for more info.
            loggers_with_no_propagation: List of logger instances to skip
               setting ``propagate = True``. This is useful if you would like
               log messages from a particular source to not appear in the root
               logger.
        """
        self.setup_python_logging_called = True
        pw_console.python_logging.setup_python_logging(
            last_resort_filename, loggers_with_no_propagation)

    def hide_windows(self, *window_titles) -> None:
        """Hide window panes specified by title on console startup."""
        for window_title in window_titles:
            self.hidden_by_default_windows.append(window_title)

    def embed(self, override_window_config: Optional[Dict] = None) -> None:
        """Start the console."""

        # Create the ConsoleApp instance.
        self.console_app = ConsoleApp(
            global_vars=self.global_vars,
            local_vars=self.local_vars,
            repl_startup_message=self.repl_startup_message,
            help_text=self.help_text,
            app_title=self.app_title,
            extra_completers=self.extra_completers,
            floating_window_plugins=self.floating_window_plugins,
        )
        PW_CONSOLE_APP_CONTEXTVAR.set(self.console_app)  # type: ignore
        # Setup Python logging and log panes.
        if not self.setup_python_logging_called:
            self.setup_python_logging()
        self._setup_log_panes()

        # Add window pane plugins to the layout.
        for window_pane in self.window_plugins:
            _set_console_app_instance(window_pane, self.console_app)
            # Hide window plugins if the title is hidden by default.
            if window_pane.pane_title() in self.hidden_by_default_windows:
                window_pane.show_pane = False
            self.console_app.window_manager.add_pane(window_pane)

        # Add toolbar plugins to the layout.
        for toolbar in self.top_toolbar_plugins:
            _set_console_app_instance(toolbar, self.console_app)
            self.console_app.window_manager.add_top_toolbar(toolbar)
        for toolbar in self.bottom_toolbar_plugins:
            _set_console_app_instance(toolbar, self.console_app)
            self.console_app.window_manager.add_bottom_toolbar(toolbar)

        # Init floating window plugins.
        for floating_window, _ in self.floating_window_plugins:
            _set_console_app_instance(floating_window, self.console_app)

        # Rebuild prompt_toolkit containers, menu items, and help content with
        # any new plugins added above.
        self.console_app.refresh_layout()

        # Load external config if passed in.
        if self.config_file_path:
            self.console_app.load_clean_config(self.config_file_path)

        if override_window_config:
            self.console_app.prefs.set_windows(override_window_config)
        self.console_app.apply_window_config()

        # Hide the repl pane if it's in the hidden windows list.
        if 'Python Repl' in self.hidden_by_default_windows:
            self.console_app.repl_pane.show_pane = False

        # Start a thread for running user code.
        self.console_app.start_user_code_thread()

        # Startup any background threads and tasks required by plugins.
        for window_pane in self.window_plugins:
            if isinstance(window_pane, PluginMixin):
                window_pane.plugin_start()
        for toolbar in self.bottom_toolbar_plugins:
            if isinstance(toolbar, PluginMixin):
                toolbar.plugin_start()
        for toolbar in self.top_toolbar_plugins:
            if isinstance(toolbar, PluginMixin):
                toolbar.plugin_start()

        # Start the prompt_toolkit UI app.
        asyncio.run(self.console_app.run(test_mode=self.test_mode),
                    debug=self.test_mode)
