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

import collections
from enum import Enum
import functools
import logging
from typing import Any, List, Optional, TYPE_CHECKING

from prompt_toolkit.filters import has_focus
from prompt_toolkit.layout import (
    Dimension,
    FormattedTextControl,
    HSplit,
    HorizontalAlign,
    VSplit,
    Window,
    WindowAlign,
)
from prompt_toolkit.mouse_events import MouseEvent, MouseEventType, MouseButton

import pw_console.style
import pw_console.widgets.mouse_handlers

if TYPE_CHECKING:
    # pylint: disable=ungrouped-imports
    from pw_console.window_manager import WindowManager

_LOG = logging.getLogger(__package__)


class DisplayMode(Enum):
    """WindowList display modes."""
    STACK = 'Stacked'
    TABBED = 'Tabbed'


DEFAULT_DISPLAY_MODE = DisplayMode.STACK

# Weighted amount for adjusting window dimensions when enlarging and shrinking.
_WINDOW_HEIGHT_ADJUST = 1


class WindowListHSplit(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_list, *args, **kwargs):
        # Save a reference to the parent window pane.
        self.parent_window_list = parent_window_list
        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_list.resize_mode:
            # Ignore future mouse_handler updates.
            new_mouse_handlers = (
                pw_console.widgets.mouse_handlers.EmptyMouseHandler())
            # Set existing mouse_handlers to the parent_window_list'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_list.mouse_handler)

        # Save the width, height, and draw position for the current render pass.
        self.parent_window_list.update_window_list_size(
            write_position.width, write_position.height, write_position.xpos,
            write_position.ypos)
        # Continue writing content to the screen.
        super().write_to_screen(screen, new_mouse_handlers, write_position,
                                parent_style, erase_bg, z_index)


class WindowList:
    """WindowList holds a stack of windows for the WindowManager."""

    # pylint: disable=too-many-instance-attributes,too-many-public-methods
    def __init__(
        self,
        window_manager: 'WindowManager',
    ):
        self.window_manager = window_manager
        self.application = window_manager.application

        self.current_window_list_width: int = 0
        self.current_window_list_height: int = 0
        self.last_window_list_width: int = 0
        self.last_window_list_height: int = 0

        self.current_window_list_xposition: int = 0
        self.last_window_list_xposition: int = 0
        self.current_window_list_yposition: int = 0
        self.last_window_list_yposition: int = 0

        self.display_mode = DEFAULT_DISPLAY_MODE
        self.active_panes: collections.deque = collections.deque()
        self.focused_pane_index: Optional[int] = None

        self.height = Dimension(preferred=10)
        self.width = Dimension(preferred=10)

        self.resize_mode = False
        self.resize_target_pane_index = None
        self.resize_target_pane = None
        self.resize_current_row = 0

        # Reference to the current prompt_toolkit window split for the current
        # set of active_panes.
        self.container = None

    def _calculate_actual_heights(self) -> List[int]:
        heights = [
            p.height.preferred if p.show_pane else 0 for p in self.active_panes
        ]
        available_height = self.current_window_list_height
        remaining_rows = available_height - sum(heights)
        window_index = 0

        # Distribute remaining unaccounted rows to each window in turn.
        while remaining_rows > 0:
            # 0 heights are hiden windows, only add +1 to visible windows.
            if heights[window_index] > 0:
                heights[window_index] += 1
                remaining_rows -= 1
            window_index = (window_index + 1) % len(heights)

        return heights

    def _update_resize_current_row(self):
        heights = self._calculate_actual_heights()
        start_row = 0

        # Find the starting row
        for i in range(self.resize_target_pane_index + 1):
            # If we are past the current pane, exit the loop.
            if i > self.resize_target_pane_index:
                break
            # 0 heights are hidden windows, only count visible windows.
            if heights[i] > 0:
                start_row += heights[i]
        self.resize_current_row = start_row

    def start_resize(self, target_pane, pane_index):
        # Can only resize if view mode is stacked.
        if self.display_mode != DisplayMode.STACK:
            return

        # Check the target_pane isn't the last one in the list
        visible_panes = [pane for pane in self.active_panes if pane.show_pane]
        if target_pane == visible_panes[-1]:
            return

        self.resize_mode = True
        self.resize_target_pane_index = pane_index
        self._update_resize_current_row()

    def stop_resize(self):
        self.resize_mode = False
        self.resize_target_pane_index = None
        self.resize_current_row = 0

    def get_tab_mode_active_pane(self):
        if self.focused_pane_index is None:
            self.focused_pane_index = 0

        pane = None
        try:
            pane = self.active_panes[self.focused_pane_index]
        except IndexError:
            # Ignore ValueError which can be raised by the self.active_panes
            # deque if existing_pane can't be found.
            self.focused_pane_index = 0
            pane = self.active_panes[self.focused_pane_index]
        return pane

    def get_current_active_pane(self):
        """Return the current active window pane."""
        focused_pane = None

        command_runner_focused_pane = None
        if self.application.command_runner_is_open():
            command_runner_focused_pane = (
                self.application.command_runner_last_focused_pane())

        for index, pane in enumerate(self.active_panes):
            in_focus = False
            if has_focus(pane)():
                in_focus = True
            elif command_runner_focused_pane and pane.has_child_container(
                    command_runner_focused_pane):
                in_focus = True

            if in_focus:
                focused_pane = pane
                self.focused_pane_index = index
                break
        return focused_pane

    def get_pane_titles(self, omit_subtitles=False, use_menu_title=True):
        fragments = []
        separator = ('', ' ')
        fragments.append(separator)
        for pane_index, pane in enumerate(self.active_panes):
            title = pane.menu_title() if use_menu_title else pane.pane_title()
            subtitle = pane.pane_subtitle()
            text = f' {title} {subtitle} '
            if omit_subtitles:
                text = f' {title} '

            fragments.append((
                # Style
                ('class:window-tab-active' if pane_index
                 == self.focused_pane_index else 'class:window-tab-inactive'),
                # Text
                text,
                # Mouse handler
                functools.partial(
                    pw_console.widgets.mouse_handlers.on_click,
                    functools.partial(self.switch_to_tab, pane_index),
                ),
            ))
            fragments.append(separator)
        return fragments

    def switch_to_tab(self, index: int):
        self.focused_pane_index = index

        # refresh_ui() will focus on the new tab container.
        self.refresh_ui()

    def set_display_mode(self, mode: DisplayMode):
        self.display_mode = mode

        if self.display_mode == DisplayMode.TABBED:
            self.focused_pane_index = 0
            # Un-hide all panes, they must be visible to switch between tabs.
            for pane in self.active_panes:
                pane.show_pane = True

        self.application.focus_main_menu()
        self.refresh_ui()

    def refresh_ui(self):
        self.window_manager.update_root_container_body()
        # Update menu after the window manager rebuilds the root container.
        self.application.update_menu_items()

        if self.display_mode == DisplayMode.TABBED:
            self.application.focus_on_container(
                self.active_panes[self.focused_pane_index])

        self.application.redraw_ui()

    def _set_window_heights(self, new_heights: List[int]):
        for pane in self.active_panes:
            if not pane.show_pane:
                continue
            pane.height = Dimension(preferred=new_heights[0])
            new_heights = new_heights[1:]

    def rebalance_window_heights(self):
        available_height = self.current_window_list_height

        old_values = [
            p.height.preferred for p in self.active_panes if p.show_pane
        ]
        # Make sure the old total is not zero.
        old_total = max(sum(old_values), 1)
        percentages = [value / old_total for value in old_values]
        new_heights = [
            int(available_height * percentage) for percentage in percentages
        ]

        self._set_window_heights(new_heights)

    def update_window_list_size(self, width, height, xposition,
                                yposition) -> None:
        """Save width and height of the repl pane for the current UI render
        pass."""
        if width:
            self.last_window_list_width = self.current_window_list_width
            self.current_window_list_width = width
        if height:
            self.last_window_list_height = self.current_window_list_height
            self.current_window_list_height = height
        if xposition:
            self.last_window_list_xposition = (
                self.current_window_list_xposition)
            self.current_window_list_xposition = xposition
        if yposition:
            self.last_window_list_yposition = (
                self.current_window_list_yposition)
            self.current_window_list_yposition = yposition

        if (self.current_window_list_width != self.last_window_list_width
                or self.current_window_list_height !=
                self.last_window_list_height):
            self.rebalance_window_heights()

    def mouse_handler(self, mouse_event: MouseEvent):
        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 update_container(self):
        """Re-create the window list split depending on the display mode."""

        if self.display_mode == DisplayMode.STACK:
            content_split = WindowListHSplit(
                self,
                list(pane for pane in self.active_panes if pane.show_pane),
                height=lambda: self.height,
                width=lambda: self.width,
            )

        elif self.display_mode == DisplayMode.TABBED:
            content_split = WindowListHSplit(
                self,
                [
                    self._create_window_tab_toolbar(),
                    self.get_tab_mode_active_pane(),
                ],
                height=lambda: self.height,
                width=lambda: self.width,
            )

        self.container = content_split

    def _create_window_tab_toolbar(self):
        tab_bar_control = FormattedTextControl(
            functools.partial(self.get_pane_titles,
                              omit_subtitles=True,
                              use_menu_title=False))
        tab_bar_window = Window(content=tab_bar_control,
                                align=WindowAlign.LEFT,
                                dont_extend_width=True)

        spacer = Window(content=FormattedTextControl([('', '')]),
                        align=WindowAlign.LEFT,
                        dont_extend_width=False)

        tab_toolbar = VSplit(
            [
                tab_bar_window,
                spacer,
            ],
            style='class:toolbar_dim_inactive',
            height=1,
            align=HorizontalAlign.LEFT,
        )
        return tab_toolbar

    def empty(self) -> bool:
        return len(self.active_panes) == 0

    def pane_index(self, pane):
        pane_index = None
        try:
            pane_index = self.active_panes.index(pane)
        except ValueError:
            # Ignore ValueError which can be raised by the self.active_panes
            # deque if existing_pane can't be found.
            pass
        return pane_index

    def add_pane_no_checks(self, pane: Any, add_at_beginning=False):
        if add_at_beginning:
            self.active_panes.appendleft(pane)
        else:
            self.active_panes.append(pane)

    def add_pane(self, new_pane, existing_pane=None, add_at_beginning=False):
        existing_pane_index = self.pane_index(existing_pane)
        if existing_pane_index is not None:
            self.active_panes.insert(new_pane, existing_pane_index + 1)
        else:
            if add_at_beginning:
                self.active_panes.appendleft(new_pane)
            else:
                self.active_panes.append(new_pane)

        self.refresh_ui()

    def remove_pane_no_checks(self, pane: Any):
        try:
            self.active_panes.remove(pane)
        except ValueError:
            # ValueError will be raised if the the pane is not found
            pass
        return pane

    def remove_pane(self, existing_pane):
        existing_pane_index = self.pane_index(existing_pane)
        if existing_pane_index is None:
            return

        self.active_panes.remove(existing_pane)
        self.refresh_ui()

        # Set focus to the previous window pane
        if len(self.active_panes) > 0:
            existing_pane_index -= 1
            try:
                self.application.focus_on_container(
                    self.active_panes[existing_pane_index])
            except ValueError:
                # ValueError will be raised if the the pane at
                # existing_pane_index can't be accessed.
                # Focus on the main menu if the existing pane is hidden.
                self.application.focus_main_menu()

        self.application.redraw_ui()

    def enlarge_pane(self):
        """Enlarge the currently focused window pane."""
        pane = self.get_current_active_pane()
        if pane:
            self.adjust_pane_size(pane, _WINDOW_HEIGHT_ADJUST)

    def shrink_pane(self):
        """Shrink the currently focused window pane."""
        pane = self.get_current_active_pane()
        if pane:
            self.adjust_pane_size(pane, -_WINDOW_HEIGHT_ADJUST)

    def mouse_resize(self, _xpos, ypos) -> None:
        if self.resize_target_pane_index is None:
            return

        target_pane = self.active_panes[self.resize_target_pane_index]

        diff = ypos - self.resize_current_row
        if not self.window_manager.vertical_window_list_spliting():
            # The mouse ypos value includes rows from other window lists. If
            # horizontal splitting is active we need to check the diff relative
            # to the starting y position row. Subtract the start y position and
            # an additional 1 for the top menu bar.
            diff -= self.current_window_list_yposition - 1

        if diff == 0:
            return
        self.adjust_pane_size(target_pane, diff)
        self._update_resize_current_row()
        self.application.redraw_ui()

    def adjust_pane_size(self,
                         pane,
                         diff: int = _WINDOW_HEIGHT_ADJUST) -> None:
        """Increase or decrease a given pane's height."""
        # Placeholder next_pane value to allow setting width and height without
        # any consequences if there is no next visible pane.
        next_pane = HSplit([],
                           height=Dimension(preferred=10),
                           width=Dimension(preferred=10))  # type: ignore
        # Try to get the next visible pane to subtract a weight value from.
        next_visible_pane = self._get_next_visible_pane_after(pane)
        if next_visible_pane:
            next_pane = next_visible_pane

        # If the last pane is selected, and there are at least 2 panes, make
        # next_pane the previous pane.
        try:
            if len(self.active_panes) >= 2 and (self.active_panes.index(pane)
                                                == len(self.active_panes) - 1):
                next_pane = self.active_panes[-2]
        except ValueError:
            # Ignore ValueError raised if self.active_panes[-2] doesn't exist.
            pass

        old_height = pane.height.preferred
        if diff < 0 and old_height <= 1:
            return
        next_old_height = next_pane.height.preferred  # type: ignore

        # Add to the current pane
        new_height = old_height + diff
        if new_height <= 0:
            new_height = old_height

        # Subtract from the next pane
        next_new_height = next_old_height - diff
        if next_new_height <= 0:
            next_new_height = next_old_height

        # If new height is too small or no change, make no adjustments.
        if new_height < 3 or next_new_height < 3 or old_height == new_height:
            return

        # Set new heigts of the target pane and next pane.
        pane.height.preferred = new_height
        next_pane.height.preferred = next_new_height  # type: ignore

    def reset_pane_sizes(self):
        """Reset all active pane heights evenly."""

        available_height = self.current_window_list_height
        old_values = [
            p.height.preferred for p in self.active_panes if p.show_pane
        ]
        new_heights = [int(available_height / len(old_values))
                       ] * len(old_values)

        self._set_window_heights(new_heights)

    def move_pane_up(self):
        pane = self.get_current_active_pane()
        pane_index = self.pane_index(pane)
        if pane_index is None or pane_index <= 0:
            # Already at the beginning
            return

        # Swap with the previous pane
        previous_pane = self.active_panes[pane_index - 1]
        self.active_panes[pane_index - 1] = pane
        self.active_panes[pane_index] = previous_pane

        self.refresh_ui()

    def move_pane_down(self):
        pane = self.get_current_active_pane()
        pane_index = self.pane_index(pane)
        pane_count = len(self.active_panes)
        if pane_index is None or pane_index + 1 >= pane_count:
            # Already at the end
            return

        # Swap with the next pane
        next_pane = self.active_panes[pane_index + 1]
        self.active_panes[pane_index + 1] = pane
        self.active_panes[pane_index] = next_pane

        self.refresh_ui()

    def _get_next_visible_pane_after(self, target_pane):
        """Return the next visible pane that appears after the target pane."""
        try:
            target_pane_index = self.active_panes.index(target_pane)
        except ValueError:
            # If pane can't be found, focus on the main menu.
            return None

        # Loop through active panes (not including the target_pane).
        for i in range(1, len(self.active_panes)):
            next_pane_index = (target_pane_index + i) % len(self.active_panes)
            next_pane = self.active_panes[next_pane_index]
            if next_pane.show_pane:
                return next_pane
        return None

    def focus_next_visible_pane(self, pane):
        """Focus on the next visible window pane if possible."""
        next_visible_pane = self._get_next_visible_pane_after(pane)
        if next_visible_pane:
            self.application.layout.focus(next_visible_pane)
            return
        self.application.focus_main_menu()
