# 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.
"""WindowManager"""

import collections
import copy
import functools
from itertools import chain
import logging
import operator
from typing import Any, Dict, Iterable, List, Optional

from prompt_toolkit.key_binding import KeyBindings
from prompt_toolkit.layout import (
    Dimension,
    HSplit,
    VSplit,
    FormattedTextControl,
    Window,
    WindowAlign,
)
from prompt_toolkit.mouse_events import MouseEvent, MouseEventType, MouseButton
from prompt_toolkit.widgets import MenuItem

from pw_console.console_prefs import ConsolePrefs, error_unknown_window
from pw_console.log_pane import LogPane
import pw_console.widgets.checkbox
from pw_console.widgets import WindowPaneToolbar
import pw_console.widgets.mouse_handlers
from pw_console.window_list import WindowList, DisplayMode

_LOG = logging.getLogger(__package__)

# Amount for adjusting window dimensions when enlarging and shrinking.
_WINDOW_SPLIT_ADJUST = 1


class WindowListResizeHandle(FormattedTextControl):
    """Button to initiate window list resize drag events."""
    def __init__(self, window_manager, window_list: Any, *args,
                 **kwargs) -> None:
        self.window_manager = window_manager
        self.window_list = window_list
        super().__init__(*args, **kwargs)

    def mouse_handler(self, mouse_event: MouseEvent):
        """Mouse handler for this control."""
        # Start resize mouse drag event
        if mouse_event.event_type == MouseEventType.MOUSE_DOWN:
            self.window_manager.start_resize(self.window_list)
            # Mouse event handled, return None.
            return None

        # Mouse event not handled, return NotImplemented.
        return NotImplemented


class WindowManagerVSplit(VSplit):
    """PromptToolkit VSplit class with some additions for size and mouse resize.

    This VSplit has a write_to_screen function that saves the width and height
    of the container for the current render pass. It also handles overriding
    mouse handlers for triggering window resize adjustments.
    """
    def __init__(self, parent_window_manager, *args, **kwargs):
        # Save a reference to the parent window pane.
        self.parent_window_manager = parent_window_manager
        super().__init__(*args, **kwargs)

    def write_to_screen(
        self,
        screen,
        mouse_handlers,
        write_position,
        parent_style: str,
        erase_bg: bool,
        z_index: Optional[int],
    ) -> None:
        new_mouse_handlers = mouse_handlers
        # Is resize mode active?
        if self.parent_window_manager.resize_mode:
            # Ignore future mouse_handler updates.
            new_mouse_handlers = (
                pw_console.widgets.mouse_handlers.EmptyMouseHandler())
            # Set existing mouse_handlers to the parent_window_managers's
            # mouse_handler. This will handle triggering resize events.
            mouse_handlers.set_mouse_handler_for_range(
                write_position.xpos,
                write_position.xpos + write_position.width,
                write_position.ypos,
                write_position.ypos + write_position.height,
                self.parent_window_manager.mouse_handler)

        # Save the width and height for the current render pass.
        self.parent_window_manager.update_window_manager_size(
            write_position.width, write_position.height)
        # Continue writing content to the screen.
        super().write_to_screen(screen, new_mouse_handlers, write_position,
                                parent_style, erase_bg, z_index)


class WindowManagerHSplit(HSplit):
    """PromptToolkit HSplit class with some additions for size and mouse resize.

    This HSplit has a write_to_screen function that saves the width and height
    of the container for the current render pass. It also handles overriding
    mouse handlers for triggering window resize adjustments.
    """
    def __init__(self, parent_window_manager, *args, **kwargs):
        # Save a reference to the parent window pane.
        self.parent_window_manager = parent_window_manager
        super().__init__(*args, **kwargs)

    def write_to_screen(
        self,
        screen,
        mouse_handlers,
        write_position,
        parent_style: str,
        erase_bg: bool,
        z_index: Optional[int],
    ) -> None:
        new_mouse_handlers = mouse_handlers
        # Is resize mode active?
        if self.parent_window_manager.resize_mode:
            # Ignore future mouse_handler updates.
            new_mouse_handlers = (
                pw_console.widgets.mouse_handlers.EmptyMouseHandler())
            # Set existing mouse_handlers to the parent_window_managers's
            # mouse_handler. This will handle triggering resize events.
            mouse_handlers.set_mouse_handler_for_range(
                write_position.xpos,
                write_position.xpos + write_position.width,
                write_position.ypos,
                write_position.ypos + write_position.height,
                self.parent_window_manager.mouse_handler)

        # Save the width and height for the current render pass.
        self.parent_window_manager.update_window_manager_size(
            write_position.width, write_position.height)
        # Continue writing content to the screen.
        super().write_to_screen(screen, new_mouse_handlers, write_position,
                                parent_style, erase_bg, z_index)


class WindowManager:
    """WindowManager class

    This class handles adding/removing/resizing windows and rendering the
    prompt_toolkit split layout."""

    # pylint: disable=too-many-public-methods,too-many-instance-attributes

    def __init__(
        self,
        application: Any,
    ):
        self.application = application
        self.window_lists: collections.deque = collections.deque()
        self.window_lists.append(WindowList(self))
        self.key_bindings = self._create_key_bindings()
        self.top_toolbars: List[WindowPaneToolbar] = []
        self.bottom_toolbars: List[WindowPaneToolbar] = []

        self.resize_mode: bool = False
        self.resize_target_window_list_index: Optional[int] = None
        self.resize_target_window_list: Optional[int] = None
        self.resize_current_row: int = 0
        self.resize_current_column: int = 0

        self.current_window_manager_width: int = 0
        self.current_window_manager_height: int = 0
        self.last_window_manager_width: int = 0
        self.last_window_manager_height: int = 0

    def update_window_manager_size(self, width, height):
        """Save width and height for the current UI render pass."""
        if width:
            self.last_window_manager_width = self.current_window_manager_width
            self.current_window_manager_width = width
        if height:
            self.last_window_manager_height = self.current_window_manager_height
            self.current_window_manager_height = height

        if (self.current_window_manager_width != self.last_window_manager_width
                or self.current_window_manager_height !=
                self.last_window_manager_height):
            self.rebalance_window_list_sizes()

    def _set_window_list_sizes(self, new_heights: List[int],
                               new_widths: List[int]) -> None:
        for window_list in self.window_lists:
            window_list.height = Dimension(preferred=new_heights[0])
            new_heights = new_heights[1:]
            window_list.width = Dimension(preferred=new_widths[0])
            new_widths = new_widths[1:]

    def vertical_window_list_spliting(self) -> bool:
        return self.application.prefs.window_column_split_method == 'vertical'

    def rebalance_window_list_sizes(self) -> None:
        """Adjust relative split sizes to fill available space."""
        available_height = self.current_window_manager_height
        available_width = self.current_window_manager_width

        old_heights = [w.height.preferred for w in self.window_lists]
        old_widths = [w.width.preferred for w in self.window_lists]

        # Make sure the old totals are not zero.
        old_height_total = max(sum(old_heights), 1)
        old_width_total = max(sum(old_widths), 1)

        height_percentages = [
            value / old_height_total for value in old_heights
        ]
        width_percentages = [value / old_width_total for value in old_widths]

        new_heights = [
            int(available_height * percentage)
            for percentage in height_percentages
        ]
        new_widths = [
            int(available_width * percentage)
            for percentage in width_percentages
        ]

        if self.vertical_window_list_spliting():
            new_heights = [
                self.current_window_manager_height for h in new_heights
            ]
        else:
            new_widths = [
                self.current_window_manager_width for h in new_widths
            ]

        self._set_window_list_sizes(new_heights, new_widths)

    def _create_key_bindings(self) -> KeyBindings:
        key_bindings = KeyBindings()
        register = self.application.prefs.register_keybinding

        @register('window-manager.move-pane-left', key_bindings)
        def move_pane_left(_event):
            """Move window pane left."""
            self.move_pane_left()

        @register('window-manager.move-pane-right', key_bindings)
        def move_pane_right(_event):
            """Move window pane right."""
            self.move_pane_right()

        @register('window-manager.move-pane-down', key_bindings)
        def move_pane_down(_event):
            """Move window pane down."""
            self.move_pane_down()

        @register('window-manager.move-pane-up', key_bindings)
        def move_pane_up(_event):
            """Move window pane up."""
            self.move_pane_up()

        @register('window-manager.enlarge-pane', key_bindings)
        def enlarge_pane(_event):
            """Enlarge the active window pane."""
            self.enlarge_pane()

        @register('window-manager.shrink-pane', key_bindings)
        def shrink_pane(_event):
            """Shrink the active window pane."""
            self.shrink_pane()

        @register('window-manager.shrink-split', key_bindings)
        def shrink_split(_event):
            """Shrink the current window split."""
            self.shrink_split()

        @register('window-manager.enlarge-split', key_bindings)
        def enlarge_split(_event):
            """Enlarge the current window split."""
            self.enlarge_split()

        @register('window-manager.focus-prev-pane', key_bindings)
        def focus_prev_pane(_event):
            """Switch focus to the previous window pane or tab."""
            self.focus_previous_pane()

        @register('window-manager.focus-next-pane', key_bindings)
        def focus_next_pane(_event):
            """Switch focus to the next window pane or tab."""
            self.focus_next_pane()

        @register('window-manager.balance-window-panes', key_bindings)
        def balance_window_panes(_event):
            """Balance all window sizes."""
            self.balance_window_sizes()

        return key_bindings

    def delete_empty_window_lists(self):
        empty_lists = [
            window_list for window_list in self.window_lists
            if window_list.empty()
        ]
        for empty_list in empty_lists:
            self.window_lists.remove(empty_list)

    def add_top_toolbar(self, toolbar: WindowPaneToolbar) -> None:
        self.top_toolbars.append(toolbar)

    def add_bottom_toolbar(self, toolbar: WindowPaneToolbar) -> None:
        self.bottom_toolbars.append(toolbar)

    def create_root_container(self):
        """Create vertical or horizontal splits for all active panes."""
        self.delete_empty_window_lists()

        for window_list in self.window_lists:
            window_list.update_container()

        vertical_split = self.vertical_window_list_spliting()

        window_containers = []
        for i, window_list in enumerate(self.window_lists):
            window_containers.append(window_list.container)
            if (i + 1) >= len(self.window_lists):
                continue

            if vertical_split:
                separator_padding = Window(
                    content=WindowListResizeHandle(self, window_list, "│"),
                    char='│',
                    width=1,
                    dont_extend_height=False,
                )
                resize_separator = HSplit(
                    [
                        separator_padding,
                        Window(
                            content=WindowListResizeHandle(
                                self, window_list, "║\n║\n║"),
                            char='│',
                            width=1,
                            dont_extend_height=True,
                        ),
                        separator_padding,
                    ],
                    style='class:pane_separator',
                )
            else:
                resize_separator = Window(
                    content=WindowListResizeHandle(self, window_list, "════"),
                    char='─',
                    height=1,
                    align=WindowAlign.CENTER,
                    dont_extend_width=False,
                    style='class:pane_separator',
                )
            window_containers.append(resize_separator)

        if vertical_split:
            split = WindowManagerVSplit(self, window_containers)
        else:
            split = WindowManagerHSplit(self, window_containers)

        split_items = []
        split_items.extend(self.top_toolbars)
        split_items.append(split)
        split_items.extend(self.bottom_toolbars)
        return HSplit(split_items)

    def update_root_container_body(self):
        # Replace the root MenuContainer body with the new split.
        self.application.root_container.container.content.children[
            1] = self.create_root_container()

    def _get_active_window_list_and_pane(self):
        active_pane = None
        active_window_list = None
        for window_list in self.window_lists:
            active_pane = window_list.get_current_active_pane()
            if active_pane:
                active_window_list = window_list
                break
        return active_window_list, active_pane

    def window_list_index(self, window_list: WindowList) -> Optional[int]:
        index = None
        try:
            index = self.window_lists.index(window_list)
        except ValueError:
            # Ignore ValueError which can be raised by the self.window_lists
            # deque if the window_list can't be found.
            pass
        return index

    def run_action_on_active_pane(self, function_name):
        _active_window_list, active_pane = (
            self._get_active_window_list_and_pane())
        if not hasattr(active_pane, function_name):
            return
        method_to_call = getattr(active_pane, function_name)
        method_to_call()
        return

    def focus_previous_pane(self) -> None:
        """Focus on the previous visible window pane or tab."""
        self.focus_next_pane(reverse_order=True)

    def focus_next_pane(self, reverse_order=False) -> None:
        """Focus on the next visible window pane or tab."""
        active_window_list, active_pane = (
            self._get_active_window_list_and_pane())
        if active_window_list is None:
            return

        # Total count of window lists and panes
        window_list_count = len(self.window_lists)
        pane_count = len(active_window_list.active_panes)

        # Get currently focused indices
        active_window_list_index = self.window_list_index(active_window_list)
        if active_window_list_index is None:
            return
        active_pane_index = active_window_list.pane_index(active_pane)

        increment = -1 if reverse_order else 1
        # Assume we can switch to the next pane in the current window_list
        next_pane_index = active_pane_index + increment

        # Case 1: next_pane_index does not exist in this window list.
        # Action: Switch to the first pane of the next window list.
        if next_pane_index >= pane_count or next_pane_index < 0:
            # Get the next window_list
            next_window_list_index = ((active_window_list_index + increment) %
                                      window_list_count)
            next_window_list = self.window_lists[next_window_list_index]

            # If tabbed window mode is enabled, switch to the first tab.
            if next_window_list.display_mode == DisplayMode.TABBED:
                if reverse_order:
                    next_window_list.switch_to_tab(
                        len(next_window_list.active_panes) - 1)
                else:
                    next_window_list.switch_to_tab(0)
                return

            # Otherwise switch to the first visible window pane.
            pane_list = next_window_list.active_panes
            if reverse_order:
                pane_list = reversed(pane_list)
            for pane in pane_list:
                if pane.show_pane:
                    self.application.focus_on_container(pane)
                    return

        # Case 2: next_pane_index does exist and display mode is tabs.
        # Action: Switch to the next tab of the current window list.
        if active_window_list.display_mode == DisplayMode.TABBED:
            active_window_list.switch_to_tab(next_pane_index)
            return

        # Case 3: next_pane_index does exist and display mode is stacked.
        # Action: Switch to the next visible window pane.
        index_range = range(1, pane_count)
        if reverse_order:
            index_range = range(pane_count - 1, 0, -1)
        for i in index_range:
            next_pane_index = (active_pane_index + i) % pane_count
            next_pane = active_window_list.active_panes[next_pane_index]
            if next_pane.show_pane:
                self.application.focus_on_container(next_pane)
                return
        return

    def move_pane_left(self):
        active_window_list, active_pane = (
            self._get_active_window_list_and_pane())
        if not active_window_list:
            return

        window_list_index = self.window_list_index(active_window_list)
        # Move left should pick the previous window_list
        target_window_list_index = window_list_index - 1

        # Check if a new WindowList should be created on the left
        if target_window_list_index == -1:
            # Add the new WindowList
            target_window_list = WindowList(self)
            self.window_lists.appendleft(target_window_list)
            self.reset_split_sizes()
            # New index is 0
            target_window_list_index = 0

        # Get the destination window_list
        target_window_list = self.window_lists[target_window_list_index]

        # Move the pane
        active_window_list.remove_pane_no_checks(active_pane)
        target_window_list.add_pane(active_pane, add_at_beginning=True)
        target_window_list.reset_pane_sizes()
        self.delete_empty_window_lists()

    def move_pane_right(self):
        active_window_list, active_pane = (
            self._get_active_window_list_and_pane())
        if not active_window_list:
            return

        window_list_index = self.window_list_index(active_window_list)
        # Move right should pick the next window_list
        target_window_list_index = window_list_index + 1

        # Check if a new WindowList should be created
        if target_window_list_index == len(self.window_lists):
            # Add a new WindowList
            target_window_list = WindowList(self)
            self.window_lists.append(target_window_list)
            self.reset_split_sizes()

        # Get the destination window_list
        target_window_list = self.window_lists[target_window_list_index]

        # Move the pane
        active_window_list.remove_pane_no_checks(active_pane)
        target_window_list.add_pane(active_pane, add_at_beginning=True)
        target_window_list.reset_pane_sizes()
        self.delete_empty_window_lists()

    def move_pane_up(self):
        active_window_list, _active_pane = (
            self._get_active_window_list_and_pane())
        if not active_window_list:
            return

        active_window_list.move_pane_up()

    def move_pane_down(self):
        active_window_list, _active_pane = (
            self._get_active_window_list_and_pane())
        if not active_window_list:
            return

        active_window_list.move_pane_down()

    def shrink_pane(self):
        active_window_list, _active_pane = (
            self._get_active_window_list_and_pane())
        if not active_window_list:
            return

        active_window_list.shrink_pane()

    def enlarge_pane(self):
        active_window_list, _active_pane = (
            self._get_active_window_list_and_pane())
        if not active_window_list:
            return

        active_window_list.enlarge_pane()

    def shrink_split(self):
        if len(self.window_lists) < 2:
            return

        active_window_list, _active_pane = (
            self._get_active_window_list_and_pane())
        if not active_window_list:
            return

        self.adjust_split_size(active_window_list, -_WINDOW_SPLIT_ADJUST)

    def enlarge_split(self):
        active_window_list, _active_pane = (
            self._get_active_window_list_and_pane())
        if not active_window_list:
            return

        self.adjust_split_size(active_window_list, _WINDOW_SPLIT_ADJUST)

    def balance_window_sizes(self):
        """Reset all splits and pane sizes."""
        self.reset_pane_sizes()
        self.reset_split_sizes()

    def reset_split_sizes(self):
        """Reset all active pane width and height to defaults"""
        available_height = self.current_window_manager_height
        available_width = self.current_window_manager_width
        old_heights = [w.height.preferred for w in self.window_lists]
        old_widths = [w.width.preferred for w in self.window_lists]
        new_heights = [int(available_height / len(old_heights))
                       ] * len(old_heights)
        new_widths = [int(available_width / len(old_widths))] * len(old_widths)

        self._set_window_list_sizes(new_heights, new_widths)

    def _get_next_window_list_for_resizing(
            self, window_list: WindowList) -> Optional[WindowList]:
        window_list_index = self.window_list_index(window_list)
        if window_list_index is None:
            return None

        next_window_list_index = ((window_list_index + 1) %
                                  len(self.window_lists))

        # Use the previous window if we are on the last split
        if window_list_index == len(self.window_lists) - 1:
            next_window_list_index = window_list_index - 1

        next_window_list = self.window_lists[next_window_list_index]
        return next_window_list

    def adjust_split_size(self,
                          window_list: WindowList,
                          diff: int = _WINDOW_SPLIT_ADJUST) -> None:
        """Increase or decrease a given window_list's vertical split width."""
        # No need to resize if only one split.
        if len(self.window_lists) < 2:
            return

        # Get the next split to subtract from.
        next_window_list = self._get_next_window_list_for_resizing(window_list)
        if not next_window_list:
            return

        if self.vertical_window_list_spliting():
            # Get current width
            old_value = window_list.width.preferred
            next_old_value = next_window_list.width.preferred  # type: ignore
        else:
            # Get current height
            old_value = window_list.height.preferred
            next_old_value = next_window_list.height.preferred  # type: ignore

        # Add to the current split
        new_value = old_value + diff
        if new_value <= 0:
            new_value = old_value

        # Subtract from the next split
        next_new_value = next_old_value - diff
        if next_new_value <= 0:
            next_new_value = next_old_value

        # If new height is too small or no change, make no adjustments.
        if new_value < 3 or next_new_value < 3 or old_value == new_value:
            return

        if self.vertical_window_list_spliting():
            # Set new width
            window_list.width.preferred = new_value
            next_window_list.width.preferred = next_new_value  # type: ignore
        else:
            # Set new height
            window_list.height.preferred = new_value
            next_window_list.height.preferred = next_new_value  # type: ignore
            window_list.rebalance_window_heights()
            next_window_list.rebalance_window_heights()

    def toggle_pane(self, pane):
        """Toggle a pane on or off."""
        window_list, _pane_index = (
            self._find_window_list_and_pane_index(pane))

        # Don't hide the window if tabbed mode is enabled. Switching to a
        # separate tab is preffered.
        if window_list.display_mode == DisplayMode.TABBED:
            return
        pane.show_pane = not pane.show_pane
        self.update_root_container_body()
        self.application.update_menu_items()

        # Set focus to the top level menu. This has the effect of keeping the
        # menu open if it's already open.
        self.application.focus_main_menu()

    def focus_first_visible_pane(self):
        """Focus on the first visible container."""
        for pane in self.active_panes():
            if pane.show_pane:
                self.application.application.layout.focus(pane)
                break

    def check_for_all_hidden_panes_and_unhide(self) -> None:
        """Scan for window_lists containing only hidden panes."""
        for window_list in self.window_lists:
            all_hidden = all(not pane.show_pane
                             for pane in window_list.active_panes)
            if all_hidden:
                # Unhide the first pane
                self.toggle_pane(window_list.active_panes[0])

    def add_pane_no_checks(self, pane: Any):
        self.window_lists[0].add_pane_no_checks(pane)

    def add_pane(self, pane: Any):
        self.window_lists[0].add_pane(pane, add_at_beginning=True)

    def first_window_list(self):
        return self.window_lists[0]

    def active_panes(self):
        """Return all active panes from all window lists."""
        return chain.from_iterable(
            map(operator.attrgetter('active_panes'), self.window_lists))

    def start_resize_pane(self, pane):
        window_list, pane_index = self._find_window_list_and_pane_index(pane)
        window_list.start_resize(pane, pane_index)

    def mouse_resize(self, xpos, ypos):
        if self.resize_target_window_list_index is None:
            return
        target_window_list = self.window_lists[
            self.resize_target_window_list_index]

        diff = ypos - self.resize_current_row
        if self.vertical_window_list_spliting():
            diff = xpos - self.resize_current_column
        if diff == 0:
            return

        self.adjust_split_size(target_window_list, diff)
        self._resize_update_current_row_column()
        self.application.redraw_ui()

    def mouse_handler(self, mouse_event: MouseEvent):
        """MouseHandler used when resize_mode == True."""
        mouse_position = mouse_event.position

        if (mouse_event.event_type == MouseEventType.MOUSE_MOVE
                and mouse_event.button == MouseButton.LEFT):
            self.mouse_resize(mouse_position.x, mouse_position.y)
        elif mouse_event.event_type == MouseEventType.MOUSE_UP:
            self.stop_resize()
            # Mouse event handled, return None.
            return None
        else:
            self.stop_resize()

        # Mouse event not handled, return NotImplemented.
        return NotImplemented

    def _calculate_actual_widths(self) -> List[int]:
        widths = [w.width.preferred for w in self.window_lists]

        available_width = self.current_window_manager_width
        # Subtract 1 for each separator
        available_width -= len(self.window_lists) - 1
        remaining_rows = available_width - sum(widths)
        window_list_index = 0
        # Distribute remaining unaccounted columns to each window in turn.
        while remaining_rows > 0:
            widths[window_list_index] += 1
            remaining_rows -= 1
            window_list_index = (window_list_index + 1) % len(widths)

        return widths

    def _calculate_actual_heights(self) -> List[int]:
        heights = [w.height.preferred for w in self.window_lists]

        available_height = self.current_window_manager_height
        # Subtract 1 for each vertical separator
        available_height -= len(self.window_lists) - 1
        remaining_rows = available_height - sum(heights)
        window_list_index = 0
        # Distribute remaining unaccounted columns to each window in turn.
        while remaining_rows > 0:
            heights[window_list_index] += 1
            remaining_rows -= 1
            window_list_index = (window_list_index + 1) % len(heights)

        return heights

    def _resize_update_current_row_column(self) -> None:
        if self.resize_target_window_list_index is None:
            return

        widths = self._calculate_actual_widths()
        heights = self._calculate_actual_heights()

        start_column = 0
        start_row = 0

        # Find the starting column
        for i in range(self.resize_target_window_list_index + 1):
            # If we are past the target window_list, exit the loop.
            if i > self.resize_target_window_list_index:
                break
            start_column += widths[i]
            start_row += heights[i]
            if i < self.resize_target_window_list_index - 1:
                start_column += 1
                start_row += 1

        self.resize_current_column = start_column
        self.resize_current_row = start_row

    def start_resize(self, window_list):
        # Check the target window_list isn't the last one.
        if window_list == self.window_lists[-1]:
            return

        list_index = self.window_list_index(window_list)
        if list_index is None:
            return

        self.resize_mode = True
        self.resize_target_window_list = window_list
        self.resize_target_window_list_index = list_index
        self._resize_update_current_row_column()

    def stop_resize(self):
        self.resize_mode = False
        self.resize_target_window_list = None
        self.resize_target_window_list_index = None
        self.resize_current_row = 0
        self.resize_current_column = 0

    def _find_window_list_and_pane_index(self, pane: Any):
        pane_index = None
        parent_window_list = None
        for window_list in self.window_lists:
            pane_index = window_list.pane_index(pane)
            if pane_index is not None:
                parent_window_list = window_list
                break
        return parent_window_list, pane_index

    def remove_pane(self, existing_pane: Any):
        window_list, _pane_index = (
            self._find_window_list_and_pane_index(existing_pane))
        if window_list:
            window_list.remove_pane(existing_pane)
            # Reset focus if this list is empty
            if len(window_list.active_panes) == 0:
                self.application.focus_main_menu()

    def reset_pane_sizes(self):
        for window_list in self.window_lists:
            window_list.reset_pane_sizes()

    def _remove_panes_from_layout(
            self, pane_titles: Iterable[str]) -> Dict[str, Any]:
        # Gather pane objects and remove them from the window layout.
        collected_panes = {}

        for window_list in self.window_lists:
            # Make a copy of active_panes to prevent mutating the while
            # iterating.
            for pane in copy.copy(window_list.active_panes):
                if pane.pane_title() in pane_titles:
                    collected_panes[pane.pane_title()] = (
                        window_list.remove_pane_no_checks(pane))
        return collected_panes

    def _set_pane_options(self, pane, options: dict) -> None:  # pylint: disable=no-self-use
        if options.get('hidden', False):
            # Hide this pane
            pane.show_pane = False
        if options.get('height', False):
            # Apply new height
            new_height = options['height']
            assert isinstance(new_height, int)
            pane.height.preferred = new_height

    def _set_window_list_display_modes(self, prefs: ConsolePrefs) -> None:
        # Set column display modes
        for column_index, column_type in enumerate(prefs.window_column_modes):
            mode = DisplayMode.STACK
            if 'tabbed' in column_type:
                mode = DisplayMode.TABBED
            self.window_lists[column_index].set_display_mode(mode)

    def _create_new_log_pane_with_loggers(self, window_title, window_options,
                                          existing_pane_titles) -> LogPane:
        if 'loggers' not in window_options:
            error_unknown_window(window_title, existing_pane_titles)

        new_pane = LogPane(application=self.application,
                           pane_title=window_title)
        # Add logger handlers
        for logger_name, logger_options in window_options.get('loggers',
                                                              {}).items():

            log_level_name = logger_options.get('level', None)
            new_pane.add_log_handler(logger_name, level_name=log_level_name)
        return new_pane

    # TODO(tonymd): Split this large function up.
    def apply_config(self, prefs: ConsolePrefs) -> None:
        """Apply window configuration from loaded ConsolePrefs."""
        if not prefs.windows:
            return

        unique_titles = prefs.unique_window_titles
        collected_panes = self._remove_panes_from_layout(unique_titles)
        existing_pane_titles = [
            p.pane_title() for p in collected_panes.values()
            if isinstance(p, LogPane)
        ]

        # Keep track of original non-duplicated pane titles
        already_added_panes = []

        for column_index, column in enumerate(prefs.windows.items()):  # pylint: disable=too-many-nested-blocks
            _column_type, windows = column
            # Add a new window_list if needed
            if column_index >= len(self.window_lists):
                self.window_lists.append(WindowList(self))

            # Set column display mode to stacked by default.
            self.window_lists[column_index].display_mode = DisplayMode.STACK

            # Add windows to the this column (window_list)
            for window_title, window_dict in windows.items():
                window_options = window_dict if window_dict else {}
                new_pane = None
                desired_window_title = window_title
                # Check for duplicate_of: Title value
                window_title = window_options.get('duplicate_of', window_title)

                # Check if this pane is brand new, ready to be added, or should
                # be duplicated.
                if (window_title not in already_added_panes
                        and window_title not in collected_panes):
                    # New pane entirely
                    new_pane = self._create_new_log_pane_with_loggers(
                        window_title, window_options, existing_pane_titles)

                elif window_title not in already_added_panes:
                    # First time adding this pane
                    already_added_panes.append(window_title)
                    new_pane = collected_panes[window_title]

                elif window_title in collected_panes:
                    # Pane added once, duplicate it
                    new_pane = collected_panes[window_title].create_duplicate()
                    # Rename this duplicate pane
                    assert isinstance(new_pane, LogPane)
                    new_pane.set_pane_title(desired_window_title)

                if new_pane:
                    # Set window size and visibility
                    self._set_pane_options(new_pane, window_options)
                    # Add the new pane
                    self.window_lists[column_index].add_pane_no_checks(
                        new_pane)
                    # Apply log filters
                    if isinstance(new_pane, LogPane):
                        new_pane.apply_filters_from_config(window_options)

        # Update column display modes.
        self._set_window_list_display_modes(prefs)
        # Check for columns where all panes are hidden and unhide at least one.
        self.check_for_all_hidden_panes_and_unhide()

        # Update prompt_toolkit containers.
        self.update_root_container_body()
        self.application.update_menu_items()

        # Focus on the first visible pane.
        self.focus_first_visible_pane()

    def create_window_menu_items(self) -> List[MenuItem]:
        """Build the [Window] menu for the current set of window lists."""
        root_menu_items = []
        for window_list_index, window_list in enumerate(self.window_lists):
            menu_items = []
            menu_items.append(
                MenuItem(
                    'Column {index} View Modes'.format(
                        index=window_list_index + 1),
                    children=[
                        MenuItem(
                            '{check} {display_mode} Windows'.format(
                                display_mode=display_mode.value,
                                check=pw_console.widgets.checkbox.
                                to_checkbox_text(
                                    window_list.display_mode == display_mode,
                                    end='',
                                )),
                            handler=functools.partial(
                                window_list.set_display_mode, display_mode),
                        ) for display_mode in DisplayMode
                    ],
                ))
            menu_items.extend(
                MenuItem(
                    '{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.toggle_pane, pane),
                        ),
                    ] + [
                        MenuItem(text,
                                 handler=functools.partial(
                                     self.application.run_pane_menu_option,
                                     handler))
                        for text, handler in pane.get_window_menu_options()
                    ],
                ) for pane_index, pane in enumerate(window_list.active_panes))
            if window_list_index + 1 < len(self.window_lists):
                menu_items.append(MenuItem('-'))
            root_menu_items.extend(menu_items)

        return root_menu_items
