# 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, 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 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.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_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) -> 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,
        )
        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)

        # 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)

        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)
