# 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.
"""ConsoleApp control class."""

import asyncio
import builtins
import functools
import importlib.resources
import logging
import os
from pathlib import Path
import sys
import time
from threading import Thread
from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple, Union

from jinja2 import Environment, DictLoader, make_logging_undefined
from prompt_toolkit.clipboard.pyperclip import PyperclipClipboard
from prompt_toolkit.layout.menus import CompletionsMenu
from prompt_toolkit.output import ColorDepth
from prompt_toolkit.application import Application
from prompt_toolkit.filters import Condition
from prompt_toolkit.styles import (
    DynamicStyle,
    merge_styles,
)
from prompt_toolkit.layout import (
    ConditionalContainer,
    Float,
    Layout,
)
from prompt_toolkit.widgets import FormattedTextToolbar
from prompt_toolkit.widgets import (
    MenuContainer,
    MenuItem,
)
from prompt_toolkit.key_binding import KeyBindings, merge_key_bindings
from prompt_toolkit.history import (
    FileHistory,
    History,
    ThreadedHistory,
)
from ptpython.layout import CompletionVisualisation  # type: ignore
from ptpython.key_bindings import (  # type: ignore
    load_python_bindings, load_sidebar_bindings,
)

from pw_console.command_runner import CommandRunner
from pw_console.console_prefs import ConsolePrefs
from pw_console.help_window import HelpWindow
import pw_console.key_bindings
from pw_console.log_pane import LogPane
from pw_console.log_store import LogStore
from pw_console.pw_ptpython_repl import PwPtPythonRepl
from pw_console.python_logging import all_loggers
from pw_console.quit_dialog import QuitDialog
from pw_console.repl_pane import ReplPane
import pw_console.style
from pw_console.test_mode import start_fake_logger
import pw_console.widgets.checkbox
from pw_console.widgets import FloatingWindowPane
import pw_console.widgets.mouse_handlers
from pw_console.window_manager import WindowManager

_LOG = logging.getLogger(__package__)
_ROOT_LOG = logging.getLogger('')

_SYSTEM_COMMAND_LOG = logging.getLogger('pw_console_system_command')

MAX_FPS = 30
MIN_REDRAW_INTERVAL = (60.0 / MAX_FPS) / 60.0


class FloatingMessageBar(ConditionalContainer):
    """Floating message bar for showing status messages."""
    def __init__(self, application):
        super().__init__(
            FormattedTextToolbar(
                (lambda: application.message if application.message else []),
                style='class:toolbar_inactive',
            ),
            filter=Condition(
                lambda: application.message and application.message != ''))


def _add_log_handler_to_pane(logger: Union[str, logging.Logger],
                             pane: 'LogPane',
                             level_name: Optional[str] = None) -> None:
    """A log pane handler for a given logger instance."""
    if not pane:
        return
    pane.add_log_handler(logger, level_name=level_name)


def get_default_colordepth(
        color_depth: Optional[ColorDepth] = None) -> ColorDepth:
    # Set prompt_toolkit color_depth to the highest possible.
    if color_depth is None:
        # Default to 24bit color
        color_depth = ColorDepth.DEPTH_24_BIT

        # If using Apple Terminal switch to 256 (8bit) color.
        term_program = os.environ.get('TERM_PROGRAM', '')
        if sys.platform == 'darwin' and 'Apple_Terminal' in term_program:
            color_depth = ColorDepth.DEPTH_8_BIT

    # Check for any PROMPT_TOOLKIT_COLOR_DEPTH environment variables
    color_depth_override = os.environ.get('PROMPT_TOOLKIT_COLOR_DEPTH', '')
    if color_depth_override:
        color_depth = ColorDepth(color_depth_override)
    return color_depth


class ConsoleApp:
    """The main ConsoleApp class that glues everything together."""

    # pylint: disable=too-many-instance-attributes,too-many-public-methods
    def __init__(
        self,
        global_vars=None,
        local_vars=None,
        repl_startup_message=None,
        help_text=None,
        app_title=None,
        color_depth=None,
        extra_completers=None,
        prefs=None,
        floating_window_plugins: Optional[List[Tuple[FloatingWindowPane,
                                                     Dict]]] = None,
    ):
        self.prefs = prefs if prefs else ConsolePrefs()
        self.color_depth = get_default_colordepth(color_depth)

        # Max frequency in seconds of prompt_toolkit UI redraws triggered by new
        # log lines.
        self.log_ui_update_frequency = 0.1  # 10 FPS
        self._last_ui_update_time = time.time()

        # Create a default global and local symbol table. Values are the same
        # structure as what is returned by globals():
        #   https://docs.python.org/3/library/functions.html#globals
        if global_vars is None:
            global_vars = {
                '__name__': '__main__',
                '__package__': None,
                '__doc__': None,
                '__builtins__': builtins,
            }

        local_vars = local_vars or global_vars

        jinja_templates = {
            t: importlib.resources.read_text('pw_console.templates', t)
            for t in importlib.resources.contents('pw_console.templates')
            if t.endswith('.jinja')
        }

        # Setup the Jinja environment
        self.jinja_env = Environment(
            # Load templates automatically from pw_console/templates
            loader=DictLoader(jinja_templates),
            # Raise errors if variables are undefined in templates
            undefined=make_logging_undefined(
                logger=logging.getLogger(__package__), ),
            # Trim whitespace in templates
            trim_blocks=True,
            lstrip_blocks=True,
        )

        self.repl_history_filename = self.prefs.repl_history
        self.search_history_filename = self.prefs.search_history

        # History instance for search toolbars.
        self.search_history: History = ThreadedHistory(
            FileHistory(self.search_history_filename))

        # Event loop for executing user repl code.
        self.user_code_loop = asyncio.new_event_loop()
        self.test_mode_log_loop = asyncio.new_event_loop()

        self.app_title = app_title if app_title else 'Pigweed Console'

        # Top level UI state toggles.
        self.load_theme(self.prefs.ui_theme)

        # Pigweed upstream RST user guide
        self.user_guide_window = HelpWindow(self, title='User Guide')
        self.user_guide_window.load_user_guide()

        # Top title message
        self.message = [('class:logo', self.app_title), ('', '  ')]

        self.message.extend(
            pw_console.widgets.checkbox.to_keybind_indicator(
                'Ctrl-p',
                'Search Menu',
                functools.partial(pw_console.widgets.mouse_handlers.on_click,
                                  self.open_command_runner_main_menu),
                base_style='class:toolbar-button-inactive',
            ))
        # One space separator
        self.message.append(('', ' '))

        # Auto-generated keybindings list for all active panes
        self.keybind_help_window = HelpWindow(self, title='Keyboard Shortcuts')

        # Downstream project specific help text
        self.app_help_text = help_text if help_text else None
        self.app_help_window = HelpWindow(self,
                                          additional_help_text=help_text,
                                          title=(self.app_title + ' Help'))
        self.app_help_window.generate_help_text()

        self.prefs_file_window = HelpWindow(self, title='.pw_console.yaml')
        self.prefs_file_window.load_yaml_text(
            self.prefs.current_config_as_yaml())

        self.floating_window_plugins: List[FloatingWindowPane] = []
        if floating_window_plugins:
            self.floating_window_plugins = [
                plugin for plugin, _ in floating_window_plugins
            ]

        # Used for tracking which pane was in focus before showing help window.
        self.last_focused_pane = None

        # Create a ptpython repl instance.
        self.pw_ptpython_repl = PwPtPythonRepl(
            get_globals=lambda: global_vars,
            get_locals=lambda: local_vars,
            color_depth=self.color_depth,
            history_filename=self.repl_history_filename,
            extra_completers=extra_completers,
        )
        self.input_history = self.pw_ptpython_repl.history

        self.repl_pane = ReplPane(
            application=self,
            python_repl=self.pw_ptpython_repl,
            startup_message=repl_startup_message,
        )
        self.pw_ptpython_repl.use_code_colorscheme(self.prefs.code_theme)

        self.system_command_output_pane: Optional[LogPane] = None

        if self.prefs.swap_light_and_dark:
            self.toggle_light_theme()

        # Window panes are added via the window_manager
        self.window_manager = WindowManager(self)
        self.window_manager.add_pane_no_checks(self.repl_pane)

        # Top of screen menu items
        self.menu_items = self._create_menu_items()

        self.quit_dialog = QuitDialog(self)

        # Key bindings registry.
        self.key_bindings = pw_console.key_bindings.create_key_bindings(self)

        # Create help window text based global key_bindings and active panes.
        self._update_help_window()

        self.command_runner = CommandRunner(
            self,
            width=self.prefs.command_runner_width,
            height=self.prefs.command_runner_height,
        )

        self.floats = [
            # Top message bar
            Float(
                content=FloatingMessageBar(self),
                top=0,
                right=0,
                height=1,
            ),
            # Centered floating help windows
            Float(
                content=self.prefs_file_window,
                top=2,
                bottom=2,
                # Callable to get width
                width=self.prefs_file_window.content_width,
            ),
            Float(
                content=self.app_help_window,
                top=2,
                bottom=2,
                # Callable to get width
                width=self.app_help_window.content_width,
            ),
            Float(
                content=self.user_guide_window,
                top=2,
                bottom=2,
                # Callable to get width
                width=self.user_guide_window.content_width,
            ),
            Float(
                content=self.keybind_help_window,
                top=2,
                bottom=2,
                # Callable to get width
                width=self.keybind_help_window.content_width,
            ),
        ]

        if floating_window_plugins:
            self.floats.extend([
                Float(content=plugin_container, **float_args)
                for plugin_container, float_args in floating_window_plugins
            ])

        self.floats.extend([
            # Completion menu that can overlap other panes since it lives in
            # the top level Float container.
            Float(
                xcursor=True,
                ycursor=True,
                content=ConditionalContainer(
                    content=CompletionsMenu(
                        scroll_offset=(lambda: self.pw_ptpython_repl.
                                       completion_menu_scroll_offset),
                        max_height=16,
                    ),
                    # Only show our completion if ptpython's is disabled.
                    filter=Condition(
                        lambda: self.pw_ptpython_repl.completion_visualisation
                        == CompletionVisualisation.NONE),
                ),
            ),
            Float(
                content=self.command_runner,
                # Callable to get width
                width=self.command_runner.content_width,
                **self.prefs.command_runner_position,
            ),
            Float(
                content=self.quit_dialog,
                top=2,
                left=2,
            ),
        ])

        # prompt_toolkit root container.
        self.root_container = MenuContainer(
            body=self.window_manager.create_root_container(),
            menu_items=self.menu_items,
            floats=self.floats,
        )

        # NOTE: ptpython stores it's completion menus in this HSplit:
        #
        # self.pw_ptpython_repl.__pt_container__()
        #   .children[0].children[0].children[0].floats[0].content.children
        #
        # Index 1 is a CompletionsMenu and is shown when:
        #   self.pw_ptpython_repl
        #     .completion_visualisation == CompletionVisualisation.POP_UP
        #
        # Index 2 is a MultiColumnCompletionsMenu and is shown when:
        #   self.pw_ptpython_repl
        #     .completion_visualisation == CompletionVisualisation.MULTI_COLUMN
        #

        # Setup the prompt_toolkit layout with the repl pane as the initially
        # focused element.
        self.layout: Layout = Layout(
            self.root_container,
            focused_element=self.pw_ptpython_repl,
        )

        # Create the prompt_toolkit Application instance.
        self.application: Application = Application(
            layout=self.layout,
            key_bindings=merge_key_bindings([
                # Pull key bindings from ptpython
                load_python_bindings(self.pw_ptpython_repl),
                load_sidebar_bindings(self.pw_ptpython_repl),
                self.window_manager.key_bindings,
                self.key_bindings,
            ]),
            style=DynamicStyle(lambda: merge_styles([
                self._current_theme,
                # Include ptpython styles
                self.pw_ptpython_repl._current_style,  # pylint: disable=protected-access
            ])),
            style_transformation=self.pw_ptpython_repl.style_transformation,
            enable_page_navigation_bindings=True,
            full_screen=True,
            mouse_support=True,
            color_depth=self.color_depth,
            clipboard=PyperclipClipboard(),
            min_redraw_interval=MIN_REDRAW_INTERVAL,
        )

    def get_template(self, file_name: str):
        return self.jinja_env.get_template(file_name)

    def run_pane_menu_option(self, function_to_run):
        # Run the function for a particular menu item.
        return_value = function_to_run()
        # It's return value dictates if the main menu should close or not.
        # - False: The main menu stays open. This is the default prompt_toolkit
        #   menu behavior.
        # - True: The main menu closes.

        # Update menu content. This will refresh checkboxes and add/remove
        # items.
        self.update_menu_items()
        # Check if the main menu should stay open.
        if not return_value:
            # Keep the main menu open
            self.focus_main_menu()

    def open_new_log_pane_for_logger(
            self,
            logger_name: str,
            level_name='NOTSET',
            window_title: Optional[str] = None) -> None:
        pane_title = window_title if window_title else logger_name
        self.run_pane_menu_option(
            functools.partial(self.add_log_handler,
                              pane_title, [logger_name],
                              log_level_name=level_name))

    def set_ui_theme(self, theme_name: str) -> Callable:
        call_function = functools.partial(
            self.run_pane_menu_option,
            functools.partial(self.load_theme, theme_name))
        return call_function

    def set_code_theme(self, theme_name: str) -> Callable:
        call_function = functools.partial(
            self.run_pane_menu_option,
            functools.partial(self.pw_ptpython_repl.use_code_colorscheme,
                              theme_name))
        return call_function

    def update_menu_items(self):
        self.menu_items = self._create_menu_items()
        self.root_container.menu_items = self.menu_items

    def open_command_runner_main_menu(self) -> None:
        self.command_runner.set_completions()
        if not self.command_runner_is_open():
            self.command_runner.open_dialog()

    def open_command_runner_loggers(self) -> None:
        self.command_runner.set_completions(
            window_title='Open Logger',
            load_completions=self._create_logger_completions)
        if not self.command_runner_is_open():
            self.command_runner.open_dialog()

    def _create_logger_completions(self) -> List[Tuple[str, Callable]]:
        completions: List[Tuple[str, Callable]] = [
            (
                'root',
                functools.partial(self.open_new_log_pane_for_logger,
                                  '',
                                  window_title='root'),
            ),
        ]

        all_logger_names = sorted([logger.name for logger in all_loggers()])

        for logger_name in all_logger_names:
            completions.append((
                logger_name,
                functools.partial(self.open_new_log_pane_for_logger,
                                  logger_name),
            ))
        return completions

    def open_command_runner_history(self) -> None:
        self.command_runner.set_completions(
            window_title='History',
            load_completions=self._create_history_completions)
        if not self.command_runner_is_open():
            self.command_runner.open_dialog()

    def _create_history_completions(self) -> List[Tuple[str, Callable]]:
        return [(
            description,
            functools.partial(self.repl_pane.insert_text_into_input_buffer,
                              text),
        ) for description, text in self.repl_pane.history_completions()]

    def open_command_runner_snippets(self) -> None:
        self.command_runner.set_completions(
            window_title='Snippets',
            load_completions=self._create_snippet_completions)
        if not self.command_runner_is_open():
            self.command_runner.open_dialog()

    def _create_snippet_completions(self) -> List[Tuple[str, Callable]]:
        completions: List[Tuple[str, Callable]] = [(
            description,
            functools.partial(self.repl_pane.insert_text_into_input_buffer,
                              text),
        ) for description, text in self.prefs.snippet_completions()]

        return completions

    def _create_menu_items(self):
        themes_submenu = [
            MenuItem('Toggle Light/Dark', handler=self.toggle_light_theme),
            MenuItem('-'),
            MenuItem(
                'UI Themes',
                children=[
                    MenuItem('Default: Dark', self.set_ui_theme('dark')),
                    MenuItem('High Contrast',
                             self.set_ui_theme('high-contrast-dark')),
                    MenuItem('Nord', self.set_ui_theme('nord')),
                    MenuItem('Nord Light', self.set_ui_theme('nord-light')),
                    MenuItem('Moonlight', self.set_ui_theme('moonlight')),
                ],
            ),
            MenuItem(
                'Code Themes',
                children=[
                    MenuItem('Code: pigweed-code',
                             self.set_code_theme('pigweed-code')),
                    MenuItem('Code: pigweed-code-light',
                             self.set_code_theme('pigweed-code-light')),
                    MenuItem('Code: material',
                             self.set_code_theme('material')),
                    MenuItem('Code: gruvbox-light',
                             self.set_code_theme('gruvbox-light')),
                    MenuItem('Code: gruvbox-dark',
                             self.set_code_theme('gruvbox-dark')),
                    MenuItem('Code: tomorrow-night',
                             self.set_code_theme('tomorrow-night')),
                    MenuItem('Code: tomorrow-night-bright',
                             self.set_code_theme('tomorrow-night-bright')),
                    MenuItem('Code: tomorrow-night-blue',
                             self.set_code_theme('tomorrow-night-blue')),
                    MenuItem('Code: tomorrow-night-eighties',
                             self.set_code_theme('tomorrow-night-eighties')),
                    MenuItem('Code: dracula', self.set_code_theme('dracula')),
                    MenuItem('Code: zenburn', self.set_code_theme('zenburn')),
                ],
            ),
        ]

        file_menu = [
            # File menu
            MenuItem(
                '[File]',
                children=[
                    MenuItem('Insert Repl Snippet',
                             handler=self.open_command_runner_snippets),
                    MenuItem('Insert Repl History',
                             handler=self.open_command_runner_history),
                    MenuItem('Open Logger',
                             handler=self.open_command_runner_loggers),
                    MenuItem(
                        'Log Table View',
                        children=[
                            MenuItem(
                                '{check} Hide Date'.format(
                                    check=pw_console.widgets.checkbox.
                                    to_checkbox_text(
                                        self.prefs.hide_date_from_log_time,
                                        end='')),
                                handler=functools.partial(
                                    self.run_pane_menu_option,
                                    functools.partial(
                                        self.toggle_pref_option,
                                        'hide_date_from_log_time')),
                            ),
                            MenuItem(
                                '{check} Show Source File'.format(
                                    check=pw_console.widgets.checkbox.
                                    to_checkbox_text(
                                        self.prefs.show_source_file, end='')),
                                handler=functools.partial(
                                    self.run_pane_menu_option,
                                    functools.partial(self.toggle_pref_option,
                                                      'show_source_file')),
                            ),
                            MenuItem(
                                '{check} Show Python File'.format(
                                    check=pw_console.widgets.checkbox.
                                    to_checkbox_text(
                                        self.prefs.show_python_file, end='')),
                                handler=functools.partial(
                                    self.run_pane_menu_option,
                                    functools.partial(self.toggle_pref_option,
                                                      'show_python_file')),
                            ),
                            MenuItem(
                                '{check} Show Python Logger'.format(
                                    check=pw_console.widgets.checkbox.
                                    to_checkbox_text(
                                        self.prefs.show_python_logger,
                                        end='')),
                                handler=functools.partial(
                                    self.run_pane_menu_option,
                                    functools.partial(self.toggle_pref_option,
                                                      'show_python_logger')),
                            ),
                        ]),
                    MenuItem('-'),
                    MenuItem(
                        'Themes',
                        children=themes_submenu,
                    ),
                    MenuItem('-'),
                    MenuItem('Exit', handler=self.exit_console),
                ],
            ),
        ]

        edit_menu = [
            MenuItem(
                '[Edit]',
                children=[
                    MenuItem('Paste to Python Input',
                             handler=self.repl_pane.
                             paste_system_clipboard_to_input_buffer),
                    MenuItem('-'),
                    MenuItem('Copy all Python Output',
                             handler=self.repl_pane.copy_all_output_text),
                    MenuItem('Copy all Python Input',
                             handler=self.repl_pane.copy_all_input_text),
                    MenuItem('-'),
                    MenuItem('Clear Python Input',
                             self.repl_pane.clear_input_buffer),
                    MenuItem('Clear Python Output',
                             self.repl_pane.clear_output_buffer),
                ],
            ),
        ]

        view_menu = [
            MenuItem(
                '[View]',
                children=[
                    #         [Menu Item             ][Keybind  ]
                    MenuItem('Focus Next Window/Tab   Ctrl-Alt-n',
                             handler=self.window_manager.focus_next_pane),
                    #         [Menu Item             ][Keybind  ]
                    MenuItem('Focus Prev Window/Tab   Ctrl-Alt-p',
                             handler=self.window_manager.focus_previous_pane),
                    MenuItem('-'),

                    #         [Menu Item             ][Keybind  ]
                    MenuItem('Move Window Up         Ctrl-Alt-Up',
                             handler=functools.partial(
                                 self.run_pane_menu_option,
                                 self.window_manager.move_pane_up)),
                    #         [Menu Item             ][Keybind  ]
                    MenuItem('Move Window Down     Ctrl-Alt-Down',
                             handler=functools.partial(
                                 self.run_pane_menu_option,
                                 self.window_manager.move_pane_down)),
                    #         [Menu Item             ][Keybind  ]
                    MenuItem('Move Window Left     Ctrl-Alt-Left',
                             handler=functools.partial(
                                 self.run_pane_menu_option,
                                 self.window_manager.move_pane_left)),
                    #         [Menu Item             ][Keybind  ]
                    MenuItem('Move Window Right   Ctrl-Alt-Right',
                             handler=functools.partial(
                                 self.run_pane_menu_option,
                                 self.window_manager.move_pane_right)),
                    MenuItem('-'),

                    #         [Menu Item             ][Keybind  ]
                    MenuItem('Shrink Height            Alt-Minus',
                             handler=functools.partial(
                                 self.run_pane_menu_option,
                                 self.window_manager.shrink_pane)),
                    #         [Menu Item             ][Keybind  ]
                    MenuItem('Enlarge Height               Alt-=',
                             handler=functools.partial(
                                 self.run_pane_menu_option,
                                 self.window_manager.enlarge_pane)),
                    MenuItem('-'),

                    #         [Menu Item             ][Keybind  ]
                    MenuItem('Shrink Column                Alt-,',
                             handler=functools.partial(
                                 self.run_pane_menu_option,
                                 self.window_manager.shrink_split)),
                    #         [Menu Item             ][Keybind  ]
                    MenuItem('Enlarge Column               Alt-.',
                             handler=functools.partial(
                                 self.run_pane_menu_option,
                                 self.window_manager.enlarge_split)),
                    MenuItem('-'),

                    #         [Menu Item            ][Keybind  ]
                    MenuItem('Balance Window Sizes       Ctrl-u',
                             handler=functools.partial(
                                 self.run_pane_menu_option,
                                 self.window_manager.balance_window_sizes)),
                ],
            ),
        ]

        window_menu_items = self.window_manager.create_window_menu_items()

        floating_window_items = []
        if self.floating_window_plugins:
            floating_window_items.append(MenuItem('-', None))
            floating_window_items.extend(
                MenuItem(
                    'Floating Window {index}: {title}'.format(
                        index=pane_index + 1,
                        title=pane.menu_title(),
                    ),
                    children=[
                        MenuItem(
                            '{check} Show/Hide Window'.format(
                                check=pw_console.widgets.checkbox.
                                to_checkbox_text(pane.show_pane, end='')),
                            handler=functools.partial(
                                self.run_pane_menu_option, pane.toggle_dialog),
                        ),
                    ] + [
                        MenuItem(text,
                                 handler=functools.partial(
                                     self.run_pane_menu_option, handler))
                        for text, handler in pane.get_window_menu_options()
                    ],
                ) for pane_index, pane in enumerate(
                    self.floating_window_plugins))
            window_menu_items.extend(floating_window_items)

        window_menu = [MenuItem('[Windows]', children=window_menu_items)]

        top_level_plugin_menus = []
        for pane in self.window_manager.active_panes():
            top_level_plugin_menus.extend(pane.get_top_level_menus())
        if self.floating_window_plugins:
            for pane in self.floating_window_plugins:
                top_level_plugin_menus.extend(pane.get_top_level_menus())

        help_menu_items = [
            MenuItem(self.user_guide_window.menu_title(),
                     handler=self.user_guide_window.toggle_display),
            MenuItem(self.keybind_help_window.menu_title(),
                     handler=self.keybind_help_window.toggle_display),
            MenuItem('-'),
            MenuItem('View Key Binding Config',
                     handler=self.prefs_file_window.toggle_display),
        ]

        if self.app_help_text:
            help_menu_items.extend([
                MenuItem('-'),
                MenuItem(self.app_help_window.menu_title(),
                         handler=self.app_help_window.toggle_display)
            ])

        help_menu = [
            # Info / Help
            MenuItem(
                '[Help]',
                children=help_menu_items,
            ),
        ]

        return (file_menu + edit_menu + view_menu + top_level_plugin_menus +
                window_menu + help_menu)

    def focus_main_menu(self):
        """Set application focus to the main menu."""
        self.application.layout.focus(self.root_container.window)

    def focus_on_container(self, pane):
        """Set application focus to a specific container."""
        # Try to focus on the given pane
        try:
            self.application.layout.focus(pane)
        except ValueError:
            # If the container can't be focused, focus on the first visible
            # window pane.
            self.window_manager.focus_first_visible_pane()

    def toggle_light_theme(self):
        """Toggle light and dark theme colors."""
        # Use ptpython's style_transformation to swap dark and light colors.
        self.pw_ptpython_repl.swap_light_and_dark = (
            not self.pw_ptpython_repl.swap_light_and_dark)
        if self.application:
            self.focus_main_menu()

    def toggle_pref_option(self, setting_name):
        self.prefs.toggle_bool_option(setting_name)

    def load_theme(self, theme_name=None):
        """Regenerate styles for the current theme_name."""
        self._current_theme = pw_console.style.generate_styles(theme_name)
        if theme_name:
            self.prefs.set_ui_theme(theme_name)

    def _create_log_pane(self,
                         title: str = '',
                         log_store: Optional[LogStore] = None) -> 'LogPane':
        # Create one log pane.
        log_pane = LogPane(application=self,
                           pane_title=title,
                           log_store=log_store)
        self.window_manager.add_pane(log_pane)
        return log_pane

    def load_clean_config(self, config_file: Path) -> None:
        self.prefs.reset_config()
        self.prefs.load_config_file(config_file)

    def apply_window_config(self) -> None:
        self.window_manager.apply_config(self.prefs)

    def refresh_layout(self) -> None:
        self.window_manager.update_root_container_body()
        self.update_menu_items()
        self._update_help_window()

    def add_log_handler(
            self,
            window_title: str,
            logger_instances: Union[Iterable[logging.Logger], LogStore],
            separate_log_panes: bool = False,
            log_level_name: Optional[str] = None) -> Optional[LogPane]:
        """Add the Log pane as a handler for this logger instance."""

        existing_log_pane = None
        # Find an existing LogPane with the same window_title.
        for pane in self.window_manager.active_panes():
            if isinstance(pane, LogPane) and pane.pane_title() == window_title:
                existing_log_pane = pane
                break

        log_store: Optional[LogStore] = None
        if isinstance(logger_instances, LogStore):
            log_store = logger_instances

        if not existing_log_pane or separate_log_panes:
            existing_log_pane = self._create_log_pane(title=window_title,
                                                      log_store=log_store)

        if isinstance(logger_instances, list):
            for logger in logger_instances:
                _add_log_handler_to_pane(logger, existing_log_pane,
                                         log_level_name)

        self.refresh_layout()
        return existing_log_pane

    def _user_code_thread_entry(self):
        """Entry point for the user code thread."""
        asyncio.set_event_loop(self.user_code_loop)
        self.user_code_loop.run_forever()

    def start_user_code_thread(self):
        """Create a thread for running user code so the UI isn't blocked."""
        thread = Thread(target=self._user_code_thread_entry,
                        args=(),
                        daemon=True)
        thread.start()

    def _test_mode_log_thread_entry(self):
        """Entry point for the user code thread."""
        asyncio.set_event_loop(self.test_mode_log_loop)
        self.test_mode_log_loop.run_forever()

    def _update_help_window(self):
        """Generate the help window text based on active pane keybindings."""
        # Add global mouse bindings to the help text.
        mouse_functions = {
            'Focus pane, menu or log line.': ['Click'],
            'Scroll current window.': ['Scroll wheel'],
        }

        self.keybind_help_window.add_custom_keybinds_help_text(
            'Global Mouse', mouse_functions)

        # Add global key bindings to the help text.
        self.keybind_help_window.add_keybind_help_text('Global',
                                                       self.key_bindings)

        self.keybind_help_window.add_keybind_help_text(
            'Window Management', self.window_manager.key_bindings)

        # Add activated plugin key bindings to the help text.
        for pane in self.window_manager.active_panes():
            for key_bindings in pane.get_all_key_bindings():
                help_section_title = pane.__class__.__name__
                if isinstance(key_bindings, KeyBindings):
                    self.keybind_help_window.add_keybind_help_text(
                        help_section_title, key_bindings)
                elif isinstance(key_bindings, dict):
                    self.keybind_help_window.add_custom_keybinds_help_text(
                        help_section_title, key_bindings)

        self.keybind_help_window.generate_help_text()

    def toggle_log_line_wrapping(self):
        """Menu item handler to toggle line wrapping of all log panes."""
        for pane in self.window_manager.active_panes():
            if isinstance(pane, LogPane):
                pane.toggle_wrap_lines()

    def focused_window(self):
        """Return the currently focused window."""
        return self.application.layout.current_window

    def command_runner_is_open(self) -> bool:
        return self.command_runner.show_dialog

    def command_runner_last_focused_pane(self) -> Any:
        return self.command_runner.last_focused_pane

    def modal_window_is_open(self):
        """Return true if any modal window or dialog is open."""
        floating_window_is_open = (self.keybind_help_window.show_window
                                   or self.prefs_file_window.show_window
                                   or self.user_guide_window.show_window
                                   or self.quit_dialog.show_dialog
                                   or self.command_runner.show_dialog)

        if self.app_help_text:
            floating_window_is_open = (self.app_help_window.show_window
                                       or floating_window_is_open)

        floating_plugin_is_open = any(
            plugin.show_pane for plugin in self.floating_window_plugins)

        return floating_window_is_open or floating_plugin_is_open

    def exit_console(self):
        """Quit the console prompt_toolkit application UI."""
        self.application.exit()

    def logs_redraw(self):
        emit_time = time.time()
        # Has enough time passed since last UI redraw due to new logs?
        if emit_time > self._last_ui_update_time + self.log_ui_update_frequency:
            # Update last log time
            self._last_ui_update_time = emit_time

            # Trigger Prompt Toolkit UI redraw.
            self.redraw_ui()

    def redraw_ui(self):
        """Redraw the prompt_toolkit UI."""
        if hasattr(self, 'application'):
            # Thread safe way of sending a repaint trigger to the input event
            # loop.
            self.application.invalidate()

    def setup_command_runner_log_pane(self) -> None:
        if not self.system_command_output_pane is None:
            return

        self.system_command_output_pane = LogPane(application=self,
                                                  pane_title='Shell Output')
        self.system_command_output_pane.add_log_handler(_SYSTEM_COMMAND_LOG,
                                                        level_name='INFO')
        self.system_command_output_pane.log_view.log_store.formatter = (
            logging.Formatter('%(message)s'))
        self.system_command_output_pane.table_view = False
        self.system_command_output_pane.show_pane = True
        # Enable line wrapping
        self.system_command_output_pane.toggle_wrap_lines()
        # Blank right side toolbar text
        self.system_command_output_pane._pane_subtitle = ' '  # pylint: disable=protected-access
        self.window_manager.add_pane(self.system_command_output_pane)

    async def run(self, test_mode=False):
        """Start the prompt_toolkit UI."""
        if test_mode:
            background_log_task = start_fake_logger(
                lines=self.user_guide_window.help_text_area.document.lines,
                log_thread_entry=self._test_mode_log_thread_entry,
                log_thread_loop=self.test_mode_log_loop)

        # Repl pane has focus by default, if it's hidden switch focus to another
        # visible pane.
        if not self.repl_pane.show_pane:
            self.window_manager.focus_first_visible_pane()

        try:
            unused_result = await self.application.run_async(
                set_exception_handler=True)
        finally:
            if test_mode:
                background_log_task.cancel()


# TODO(tonymd): Remove this alias when not used by downstream projects.
def embed(
    *args,
    **kwargs,
) -> None:
    """PwConsoleEmbed().embed() alias."""
    # Import here to avoid circular dependency
    from pw_console.embed import PwConsoleEmbed  # pylint: disable=import-outside-toplevel
    console = PwConsoleEmbed(*args, **kwargs)
    console.embed()
